Fix: Patch for Parallel Tools 9.0.23350 to support Linux Kernel 3.12 (Ubuntu 14.04)

eugenesan

Bit poster
Below is a patch to fix recent changes in uid/gid treatment for filesystems.
Above also required changes in parameters parsing, so I replaced custom parameters parsing with Kernel's native routines.
Not extensively tested but works fine for me.

(I had to paste it here inline since Attachment upload is broken under Chrome and Firefox... which means TABs are not preserved)

Usage:
1) Mount Parallells Tools CD in virtual machine (Virtual Machine -> Install/Reinstall Parallels Tools)
2) Make temporary copy of Parallels Tools, enter and patch it:
$ cp -R /media/$USER/Parallels\ Tools /tmp/
$ cd /tmp/Parallels\ Tools/kmods
$ tar -xaf prl_mod.tar.gz
$ patch -p1 -d prl_fs < parallels-tools-linux-3.12-prl-fs-9.0.23350.941886.patch
$ tar -czf prl_mod.tar.gz prl_eth prl_fs prl_fs_freeze prl_tg Makefile.kmods dkms.conf
3) Install normally:
$ sudo /tmp/Parallels\ Tools/install
4) If successfully installed, reboot

Code:
diff -Nru prl_fs.orig/SharedFolders/Guest/Linux/prl_fs/inode.c prl_fs/SharedFolders/Guest/Linux/prl_fs/inode.c
--- prl_fs.orig/SharedFolders/Guest/Linux/prl_fs/inode.c	2013-11-11 17:56:58.000000000 +0200
+++ prl_fs/SharedFolders/Guest/Linux/prl_fs/inode.c	2013-11-29 20:41:53.689167040 +0200
@@ -199,10 +199,18 @@
 	if (attr->valid & _PATTR_MODE)
 		inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 0777);
 	if ((attr->valid & _PATTR_UID) &&
-	    (sbi->plain || sbi->share || attr->uid == -1))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+	    (sbi->plain || sbi->share || __kuid_val(attr->uid) == -1))
+#else
+	    (sbi->plain || sbi->share || attr->uid == -1)))
+#endif
 		inode->i_uid = attr->uid;
 	if ((attr->valid & _PATTR_GID) &&
-	    (sbi->plain || sbi->share || attr->gid == -1))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+	    (sbi->plain || sbi->share || __kgid_val(attr->gid) == -1))
+#else
+	    (sbi->plain || sbi->share || attr->gid == -1)))
+#endif
 		inode->i_gid = attr->gid;
 	return;
 }
@@ -521,13 +529,21 @@
 
 	generic_fillattr(dentry->d_inode, stat);
 	if (PRLFS_SB(dentry->d_sb)->share) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+		if (__kuid_val(stat->uid) != -1)
+#else
 		if (stat->uid != -1)
+#endif
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
 			stat->uid = current->fsuid;
 #else
 			stat->uid = current->cred->fsuid;
 #endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+		if (__kgid_val(stat->gid) != -1)
+#else
 		if (stat->gid != -1)
+#endif
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
 			stat->gid = current->fsgid;
 #else
@@ -577,9 +593,17 @@
 	mode = inode->i_mode;
 	isdir = S_ISDIR(mode);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+	if (__kuid_val(inode->i_uid) != -1)
+#else
 	if (inode->i_uid != -1)
+#endif
 		mode = mode >> 6;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+	else if (__kgid_val(inode->i_gid) != -1)
+#else
 	else if (inode->i_gid != -1)
+#endif
 		mode = mode >> 3;
 	mode &= 0007;
 	mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
diff -Nru prl_fs.orig/SharedFolders/Guest/Linux/prl_fs/prlfs.h prl_fs/SharedFolders/Guest/Linux/prl_fs/prlfs.h
--- prl_fs.orig/SharedFolders/Guest/Linux/prl_fs/prlfs.h	2013-11-11 17:56:58.000000000 +0200
+++ prl_fs/SharedFolders/Guest/Linux/prl_fs/prlfs.h	2013-11-29 20:46:27.662771996 +0200
@@ -28,8 +28,13 @@
 	struct	pci_dev *pdev;
 	unsigned sfid;
 	unsigned ttl;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+	kuid_t uid;
+	kgid_t gid;
+#else
 	uid_t uid;
 	gid_t gid;
+#endif
 	int readonly;
 	int share;
 	int plain;
diff -Nru prl_fs.orig/SharedFolders/Guest/Linux/prl_fs/super.c prl_fs/SharedFolders/Guest/Linux/prl_fs/super.c
--- prl_fs.orig/SharedFolders/Guest/Linux/prl_fs/super.c	2013-11-11 17:56:58.000000000 +0200
+++ prl_fs/SharedFolders/Guest/Linux/prl_fs/super.c	2013-11-29 20:28:39.212000000 +0200
@@ -13,6 +13,7 @@
 #include <linux/seq_file.h>
 #include <linux/ctype.h>
 #include <linux/vfs.h>
+#include <linux/parser.h>
 #include "prlfs.h"
 #include "prlfs_compat.h"
 
@@ -26,38 +27,35 @@
 extern struct file_operations prlfs_names_fops;
 extern struct inode_operations prlfs_names_iops;
 
-static int prlfs_strtoui(char *cp, unsigned *result){
-	int ret = 0;
-	unsigned ui = 0;
-	unsigned digit;
-
-	if (!cp || (*cp == 0))
-		return -EINVAL;
-
-	while (*cp) {
-		if (isdigit(*cp)) {
-			digit = *cp - '0';
-		} else {
-			ret = -EINVAL;
-			break;
-		}
-		if (ui > ui * 10U + digit)
-			return -EINVAL;
-		ui = ui * 10U + digit;
-		cp++;
-	}
-
-	if (ret == 0)
-		*result = ui;
-
-	return ret;
-}
+enum {
+	Opt_uid,
+	Opt_gid,
+	Opt_ttl,
+	Opt_nls,
+	Opt_share,
+	Opt_plain,
+	Opt_sf,
+	Opt_err,
+};
+
+static const match_table_t prlfs_tokens = {
+	{Opt_uid, "uid=%d"},
+	{Opt_gid, "gid=%d"},
+	{Opt_ttl, "ttl=%u"},
+	{Opt_nls, "nls=%s"},
+	{Opt_share, "share"},
+	{Opt_plain, "plain"},
+	{Opt_sf, "sf=%s"},
+	{Opt_err, NULL}
+};
 
 static int
 prlfs_parse_mount_options(char *options, struct prlfs_sb_info *sbi)
 {
+	substring_t args[MAX_OPT_ARGS];
 	int ret = 0;
-	char *opt, *val;
+	int val;
+	char *opt;
 
 	DPRINTK("ENTER\n");
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
@@ -70,35 +68,54 @@
 	sbi->ttl = HZ;
 
 	if (!options)
-	       goto out;
+		goto out;
 
-	while (!ret && (opt = strsep(&options, ",")) != NULL)
+	while (!ret && ((opt = strsep(&options, ",")) != NULL))
 	{
+		int token;
 		if (!*opt)
 			continue;
 
-		val = strchr(opt, '=');
-		if (val) {
-			*(val++) = 0;
-			if (strlen(val) == 0)
-				val = NULL;
-		}
-		if (!strcmp(opt, "ttl") && val)
-			ret = prlfs_strtoui(val, &sbi->ttl);
-		else if (!strcmp(opt, "uid") && val)
-			ret = prlfs_strtoui(val, &sbi->uid);
-		else if (!strcmp(opt, "gid") && val)
-			ret = prlfs_strtoui(val, &sbi->gid);
-		else if (!strcmp(opt, "nls") && val)
-			strncpy(sbi->nls, val, LOCALE_NAME_LEN - 1);
-		else if (!strcmp(opt, "share"))
+		token = match_token(opt, prlfs_tokens, args);
+		switch (token) {
+		case Opt_uid:
+			if (!(ret = match_int(&args[0], &val)))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+			sbi->uid = KUIDT_INIT(val);
+#else
+			sbi->uid = val;
+#endif
+			break;
+		case Opt_gid:
+			if (!(ret = match_int(&args[0], &val)))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+			sbi->gid = KGIDT_INIT(val);
+#else
+			sbi->gid = val;
+#endif
+			break;
+		case Opt_ttl:
+			if (!(ret = match_int(&args[0], &val)))
+				sbi->ttl = val;
+			break;
+		case Opt_nls:
+			if (!match_strlcpy(sbi->nls, &args[0], LOCALE_NAME_LEN - 1))
+				ret = -EINVAL;
+			break;
+		case Opt_share:
 			sbi->share = 1;
-		else if (!strcmp(opt, "plain"))
+			break;
+		case Opt_plain:
 			sbi->plain = 1;
-		else if (!strcmp(opt, "sf") && val)
-			strncpy(sbi->name, val, sizeof(sbi->name));
-		else
+			break;
+		case Opt_sf:
+			if (!match_strlcpy(sbi->name, &args[0], sizeof(sbi->name)))
+				ret = -EINVAL;
+			break;
+		default:
 			ret = -EINVAL;
+		}
+		DPRINTK("PARSE interating %d:%d:%s\n", token, val, args[0]);
 	}
 out:
 	DPRINTK("EXIT returning %d\n", ret);
diff -Nru prl_fs.orig/SharedFolders/Interfaces/sf_lin.h prl_fs/SharedFolders/Interfaces/sf_lin.h
--- prl_fs.orig/SharedFolders/Interfaces/sf_lin.h	2013-11-11 18:11:49.000000000 +0200
+++ prl_fs/SharedFolders/Interfaces/sf_lin.h	2013-11-29 03:11:48.924415600 +0200
@@ -40,8 +40,13 @@
 	unsigned long long mtime;
 	unsigned long long ctime;
 	unsigned int mode;
-	unsigned int uid;
-	unsigned int gid;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+	kuid_t uid;
+	kgid_t gid;
+#else
+	uid_t uid;
+	gid_t gid;
+#endif
 	unsigned int valid;
 } PACKED;
 SFLIN_CHECK_SIZE(prlfs_attr, sizeof(struct prlfs_attr), 48)

(Sorry for "stealing" formatting from similar post)
 
Last edited:
I just bought an upgrade to parallels 9 to be able to use this patch but the patch is not working with parallels tools version 9.0.24229.991745.

Where can I download the version of parallels tools that works with this patch?
Is there a working patch for this version? When will parallels support 3.12 kernel without patching?
patching file SharedFolders/Guest/Linux/prl_fs/inode.c
Hunk #1 FAILED at 199.
Hunk #2 FAILED at 521.
Hunk #3 FAILED at 577.
3 out of 3 hunks FAILED -- saving rejects to file SharedFolders/Guest/Linux/prl_fs/inode.c.rej
patching file SharedFolders/Guest/Linux/prl_fs/prlfs.h
Hunk #1 FAILED at 28.
1 out of 1 hunk FAILED -- saving rejects to file SharedFolders/Guest/Linux/prl_fs/prlfs.h.rej
patching file SharedFolders/Guest/Linux/prl_fs/super.c
Hunk #3 FAILED at 68.
1 out of 3 hunks FAILED -- saving rejects to file SharedFolders/Guest/Linux/prl_fs/super.c.rej
patching file SharedFolders/Interfaces/sf_lin.h
 
Last edited:
How to get a terminal?

I have 9.0.24229. I installed to 14.04 and installed Parallels tools, and turned off and on the 3d acceleration. Yet I see a desktop that cannot be resized, and that just has a Parallels folders icon on it. How do I get a terminal window to apply your patch?

Also, selecting reinstall Parallels Tools does not seem to mount it in /mount/$USER
 
Last edited:
I have 9.0.24229. I installed to 14.04 and installed Parallels tools, and turned off and on the 3d acceleration. Yet I see a desktop that cannot be resized, and that just has a Parallels folders icon on it. How do I get a terminal window to apply your patch?

Honestly I don't understand why you want apply this patch if I it is obsolete. Latest Parallels Tools simply work without any patching. Just make sure you have installed/update it against any kernel update.
 
Back
Top