[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gfarm-discuss:04155] Re: Gfarm + Autofs



Hello,

    Follow-up my effort to do autofs+gfarm. We found that gfarmfs-fuse sometimes hang up infinitely with some unknown reason. We manage to find out that there's a fusermount -u process that try to unmount automounted gfarmfs, though we still don't know why this unmount process is created, sending SIGINT to this process will stop the frozen process and it'll continue normally. It's looks like gfarmfs-fuse will behave strangely if there's an unmount attempt at the same time as mount attempt, but we still don't sure about this.

    Also, attached with this e-mail added some few update to my previous patch. It add capability to specify uid=xxx and gid=xxx as user name instead of user id.     Moreover, it added "map_home" option, which will map gfarm:/<username> directly to the mount point, instead of gfarm:/. The permission problem is still there.

Somsak Sriprayoonsakul wrote:
Yes. Other can also write to others home directory as well :). Actually it's quite weird, sometimes user can't create the file ("Permission Denied"). Sometimes the file can be created. But without allow_other, none except root can access gfarm.

I agree that patching autofs to have better support for fuse would be better. But for now, I try to follow the same scheme as vfat+autofs where only specific user can access the directory. Could you suggest the solution?

Thank you very much.

Osamu Tatebe wrote:
Hi Somsak,

Thanks for the great contribution!  I also tried to work with autofs
once, but could not find a smart solution for that.

I have a question about allow_others.  I think if it is mounted with
allow_others option, the mount directory can be accessed by anyone but
using the mounting user's privilege.  In this case, Gfarm security is
not applied to.  Would you make sure again whether anyone can create
files or not?  I guess anyone can create files as if everyone were a
user that mounts with allow_others.

I think it is better to work with autofs such that autofs can utilize
fuse (i.e., mounting in userspace) instead of switching a user before
every Gfarm function call.  It should be easier, much secure and also
smarter, I think.  How do you think?

Thanks,
Osamu

On Fri, 08 Sep 2006 18:18:51 +0700
Somsak Sriprayoonsakul <somsak_sr@xxxxxxxxxxxxxx> wrote:

  
Hello,

    On the course of trying to make gfarm-fuse automatic using autofs. 
Since I found no documents/guide related to this topics, so I did some 
patching to gfarmfs-fuse and make it works with my autofs. Attached with 
this e-mail is the patch that make gfarmfs-fuse obay uid= and gid= 
options of fuse. Here's my set-up

/etc/auto.master: /grid /etc/auto.grid   --timeout=1200

    /etc/auto.grid is the program map. Somehow the program map is not 
working on compute nodes of ROCKS 4.2 so I have to switch back to file 
map. Program map is better since fuse only accept numeric value of uid 
and gid. Below are my program map.

/etc/auto.grid:
uid=$(id -u)
gid=$(id -g)
echo "-fstype=fuse,uid=$uid,gid=$gid,allow_other   gfarmfs"

Platform: ROCKS 4.1 (RHEL4) on x86_64
Gfarm: 1.3.1 (no GSI). We're using Gfarm as Cluster file system.
Gfarmfs-fuse: 1.2.1

    When user access /grid/user1, their gfarm home will be mapped to 
/grid/user1/user1. This works quite well. allow_other is a must, since 
fuse will consider this mount as root, but we need to allow the real 
owner to access it. But only the real owner can create the file since 
gfarm security is still apply.

    I put seteuid/setegid wrap around every function to make gfarm 
believe that it run by that user (I put some condition so only root can 
do this). Will we have any other security issue with this patched? Also, 
sometimes the gfarmfs is lock up. I don't sure why, but it come back to 
work again when I do "killall -9 gfarmfs fusermount" :). Don't sure 
whether this is the result of my seteuid/setegid patch.

Regards,

-- 
-----------------------------------------------------------------------------------
Somsak Sriprayoonsakul

Thai National Grid Center
Software Industry Promotion Agency
Ministry of ICT, Thailand
somsak_sr@xxxxxxxxxxxxxx
-----------------------------------------------------------------------------------


    

  


-- 
-----------------------------------------------------------------------------------
Somsak Sriprayoonsakul

Thai National Grid Center
Software Industry Promotion Agency
Ministry of ICT, Thailand
somsak_sr@xxxxxxxxxxxxxx
-----------------------------------------------------------------------------------


-- 
-----------------------------------------------------------------------------------
Somsak Sriprayoonsakul

Thai National Grid Center
Software Industry Promotion Agency
Ministry of ICT, Thailand
somsak_sr@xxxxxxxxxxxxxx
-----------------------------------------------------------------------------------
--- gfarmfs-fuse-1.2.1/gfarmfs.c	2006-02-01 10:52:04.000000000 +0700
+++ gfarmfs-fuse-1.2.1-mod/gfarmfs.c	2006-09-26 23:26:53.000000000 +0700
@@ -31,6 +31,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <pwd.h>
+#include <grp.h>
 #include <libgen.h>
 #include <stdlib.h>
 #include <time.h>
@@ -65,13 +66,46 @@
 static int enable_gfarm_unbuf = 0;
 static char *arch_name = NULL;
 
+static int enable_priv = 0;
+static uid_t gfarm_run_uid = -1;
+static gid_t gfarm_run_gid = -1;
+static uid_t old_uid = -1;
+static gid_t old_gid = -1;
+
+static char * home_dir = NULL;
+
+static void set_priv(void)
+{
+	if(enable_priv) {
+		setegid(gfarm_run_gid);
+		seteuid(gfarm_run_uid);
+	}
+}
+
+static void unset_priv(void)
+{
+	if(enable_priv) {
+		seteuid(old_uid);
+		setegid(old_gid);
+	}
+}
+
 /* This is necessary to free the memory space by free(). */
 static char *
 add_gfarm_prefix(const char *path)
 {
 	char *url;
-	url = malloc(strlen(path) + 7);
-	sprintf(url, "gfarm:%s", path);
+	size_t len = strlen(path) + 7;
+
+	if(home_dir) {
+		len += (strlen(home_dir) + 1);
+	}
+	if( (url = malloc(len)) == NULL) return NULL;
+	if(!home_dir) {
+		sprintf(url, "gfarm:%s", path);
+	} else {
+		sprintf(url, "gfarm:/%s%s", home_dir, path);
+	}
 	return (url);
 }
 
@@ -81,8 +115,13 @@
 add_gfarm_prefix_symlink_suffix(const char *path)
 {
 	char *url;
-	url = malloc(strlen(path) + 7 + strlen(SYMLINK_SUFFIX));
-	sprintf(url, "gfarm:%s%s", path, SYMLINK_SUFFIX);
+
+	if( (url = malloc(strlen(path) + 7 + strlen(SYMLINK_SUFFIX))) == NULL) return NULL;
+	if(!home_dir) {
+		sprintf(url, "gfarm:%s%s", path, SYMLINK_SUFFIX);
+	} else {
+		sprintf(url, "gfarm:/%s%s%s", home_dir,path, SYMLINK_SUFFIX);
+	}
 	return (url);
 }
 #endif
@@ -100,6 +139,8 @@
 static int
 gfarmfs_final(char *e, int val_noerror, const char *name)
 {
+	int retval ;
+
 	if (e == NULL) {
 		return (val_noerror);
 	} else {
@@ -110,7 +151,9 @@
 				fprintf(stderr, "error: %s\n", e);
 			}
 		}
-		return -gfarm_error_to_errno(e);
+		retval = -gfarm_error_to_errno(e);
+		
+		return retval;
 	}
 }
 
@@ -132,6 +175,7 @@
 		}
 		gfs_closedir(dir);
 	}
+	
 	if (res == 0) {
 		return (2);
 	} else {
@@ -168,10 +212,12 @@
 		e = gfs_access(url, X_OK);
 		if (e == NULL) {
 			e = gfs_pio_set_view_section(gf, arch_name, NULL, 0);
-			return (e);
+			
+			return e;
 		}
 	}
-	return (NULL);
+	
+	return NULL;
 }
 
 static char *
@@ -182,6 +228,7 @@
 	if (arch_name != NULL &&
 	    (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0) {
 		e = gfs_pio_set_view_section(gf, arch_name, NULL, 0);
+		
 		return (e);
 	} else {
 		return (NULL);
@@ -205,6 +252,7 @@
 		e = gfs_pio_close(gf);
 		if (e2 != NULL) e = e2;
 	}
+	
 	free(url);
 	return (e);
 }
@@ -244,6 +292,7 @@
 			}
 		}
 		gfarmfs_fastcreate_free();
+		
 		return (e);
 	} else {
 		return (NULL);  /* do nothing */
@@ -254,6 +303,7 @@
 gfarmfs_fastcreate_save(const char *path, mode_t mode)
 {
 	gfarmfs_fastcreate_flush();
+	
 
 	fc.path = strdup(path);
 	if (fc.path == NULL) {
@@ -273,6 +323,7 @@
 	char *url;
 
 	url = add_gfarm_prefix(path);
+	
 	if (fc.path != NULL && strcmp(fc.path, path) == 0) {
 		if (gfarmfs_debug >= 2) {
 			printf("fastcreate open: %s\n", path);
@@ -293,6 +344,7 @@
 				*gfp, url);
 		}
 	}
+	
 	free(url);
 	return (e);
 }
@@ -308,8 +360,9 @@
 		buf->st_ino = 12345;    /* XXX */
 		buf->st_mode = fc.mode;
 		buf->st_nlink = 1;
-		buf->st_uid = getuid();
-		buf->st_gid = getgid();
+		buf->st_uid = gfarm_run_uid;
+		buf->st_gid = gfarm_run_gid;
+
 		buf->st_size = 0;
 		buf->st_blksize = GFS_BLKSIZE;
 		buf->st_blocks = 0;
@@ -341,8 +394,13 @@
 #endif
 	static struct passwd *p_save = NULL;
 	static char *username_save = NULL;
+	int retval;
 
+	set_priv();
+	
 	if (enable_fastcreate == 1 && gfarmfs_fastcreate_getattr(path, buf)) {
+		setegid(old_uid);
+		seteuid(old_gid);
 		return (0);
 	}
 
@@ -396,8 +454,8 @@
 			username_save = strdup(gs.st_user);
 			p_save = p;
 		} else {
-			buf->st_uid = getuid();
-			buf->st_gid = getgid();
+			buf->st_uid = gfarm_run_uid;
+			buf->st_gid = gfarm_run_gid;
 		}
 
 		buf->st_size = gs.st_size;
@@ -410,7 +468,10 @@
 	}
 	free(url);
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
@@ -420,7 +481,10 @@
 	struct gfs_dirent *entry;
 	char *e;
 	char *url;
+	int retval;
 
+	set_priv();
+	
 	gfarmfs_fastcreate_check();
 	e = gfarmfs_init();
 	if (e == NULL) {
@@ -443,13 +507,17 @@
 		}
 		e = gfs_closedir(dir);
 	}
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
 gfarmfs_mknod(const char *path, mode_t mode, dev_t rdev)
 {
 	char *e;
+	int retval;
 
 	if (rdev != 0 && ((rdev & S_IFREG) != S_IFREG)) {
 		if (gfarmfs_debug >= 1) {
@@ -458,12 +526,17 @@
 		return (-ENOSYS);  /* XXX */
 	}
 
+	set_priv();
+	
 	if (enable_fastcreate == 1) {
 		e = gfarmfs_fastcreate_save(path, mode);
 	} else {
 		e = gfarmfs_create_empty_file(path, mode);
 	}
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
@@ -471,7 +544,10 @@
 {
 	char *e;
 	char *url;
+	int retval;
 
+	set_priv();
+	
 	gfarmfs_fastcreate_check();
 	url = add_gfarm_prefix(path);
 	e = gfarmfs_init();
@@ -480,7 +556,10 @@
 	}
 	free(url);
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
@@ -488,7 +567,10 @@
 {
 	char *e;
 	char *url;
+	int retval;
 
+	set_priv();
+	
 	gfarmfs_fastcreate_check();
 	if ((e = gfarmfs_init()) != NULL) goto end;
 
@@ -543,7 +625,10 @@
 		free(url);
 	}
 end:
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
@@ -551,7 +636,10 @@
 {
 	char *e;
 	char *url;
+	int retval;
 
+	
+	set_priv();
 	gfarmfs_fastcreate_check();
 	url = add_gfarm_prefix(path);
 	e = gfarmfs_init();
@@ -560,7 +648,10 @@
 	}
 	free(url);
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
@@ -571,13 +662,15 @@
 	char *e;
 	char *url;
 	GFS_File gf;
-	int n = 0;
+	int n = 0, retval;
 
 	gfarmfs_fastcreate_check();
 	if (enable_symlink == 0) {
 		return (-ENOSYS);
 	}
 
+	
+	set_priv();
 	url = add_gfarm_prefix_symlink_suffix(path);
 	e = gfarmfs_init();
 	while (e == NULL) {
@@ -591,7 +684,10 @@
 
 	buf[n] = '\0';
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 #else
 	gfarmfs_fastcreate_check();
 	return (-ENOSYS);
@@ -607,7 +703,10 @@
 	char *url;
 	GFS_File gf;
 	int n, len;
+	int retval;
 
+	
+	set_priv();
 	gfarmfs_fastcreate_check();
 	if (enable_symlink == 0) {
 		return (-ENOSYS);
@@ -633,7 +732,10 @@
 	}
 	free(url);
 
-	return gfarmfs_final(e, 0, to);
+	retval = gfarmfs_final(e, 0, to);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 #else
 	gfarmfs_fastcreate_check();
 	return (-ENOSYS);
@@ -646,7 +748,10 @@
 	char *e;
 	char *from_url;
 	char *to_url;
+	int retval;
 
+	
+	set_priv();
 	gfarmfs_fastcreate_check();
 	e = gfarmfs_init();
 	if (e == NULL) {
@@ -672,7 +777,10 @@
 		free(from_url);
 		free(to_url);
 	}
-	return gfarmfs_final(e, 0, to);
+	retval = gfarmfs_final(e, 0, to);
+	setegid(old_uid);
+	seteuid(old_gid);
+	return retval;
 }
 
 static int
@@ -687,12 +795,15 @@
 	int m, n;
 	char buf[4096];
 	int symlinkmode = 0;
+	int retval;
 
 	gfarmfs_fastcreate_check();
 	if (enable_linkiscopy == 0) {
 		return (-ENOSYS);
 	}
 
+	
+	set_priv();
 	if (gfarmfs_debug >= 2) {
 		printf("hard link is replaced by copy: %s\n", to);
 	}
@@ -767,7 +878,10 @@
 	if (to_opened == 1) {
 		gfs_pio_close(to_gf);
 	}
-	return gfarmfs_final(e, 0, to);
+	retval = gfarmfs_final(e, 0, to);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
@@ -775,16 +889,24 @@
 {
 	char *e;
 	char *url;
+	int retval;
 
 	gfarmfs_fastcreate_check();
 	url = add_gfarm_prefix(path);
+	set_priv();
+	
 	e = gfarmfs_init();
 	if (e == NULL) {
 		e = gfs_chmod(url, mode);
 	}
 	free(url);
+	unset_priv();
+	
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
@@ -794,7 +916,10 @@
 	char *e;
 	char *url;
 	struct gfs_stat s;
+	int retval;
 
+	set_priv();
+	
 	gfarmfs_fastcreate_check();
 	e = gfarmfs_init();
 	if (e == NULL) {
@@ -811,7 +936,10 @@
 			gfs_stat_free(&s);
 		}
 	}
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
@@ -820,9 +948,12 @@
 	char *e;
 	GFS_File gf;
 	char *url;
+	int retval;
 
 	gfarmfs_fastcreate_check();
 	url = add_gfarm_prefix(path);
+	set_priv();
+	
 	e = gfarmfs_init();
 	while (e == NULL) {
 		e = gfs_pio_open(url, GFARM_FILE_WRONLY, &gf);
@@ -837,7 +968,10 @@
 	}
 	free(url);
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
@@ -845,9 +979,12 @@
 {
 	char *e;
 	char *url;
+	int retval;
 
 	gfarmfs_fastcreate_check();
 	url = add_gfarm_prefix(path);
+	set_priv();
+	
 	e = gfarmfs_init();
 	if (e == NULL) {
 		if (buf == NULL)
@@ -864,7 +1001,10 @@
 	}
 	free(url);
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
@@ -872,9 +1012,11 @@
 {
 	char *e;
 	char *url;
-	int flags = 0;
+	int flags = 0, retval;
 	GFS_File gf;
 
+	set_priv();
+	
 	e = gfarmfs_init();
 	while (e == NULL) {
 		if ((fi->flags & O_ACCMODE) == O_RDONLY) {
@@ -914,7 +1056,10 @@
 		break;
 	}
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
@@ -922,26 +1067,34 @@
 {
 	char *e;
 	GFS_File gf;
+	int retval;
 
 	gfarmfs_fastcreate_check();
+	set_priv();
+	
 	e = gfarmfs_init();
 	if (e == NULL) {
 		gf = (GFS_File) fi->fh;
 		e = gfs_pio_close(gf);
 	}
 
-	return gfarmfs_final(e, 0, path);
+	retval = gfarmfs_final(e, 0, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
 gfarmfs_read(const char *path, char *buf, size_t size, off_t offset,
 	     struct fuse_file_info *fi)
 {
-	int n;
+	int n, retval;
 	file_offset_t off;
 	char *e;
 	GFS_File gf;
 
+	set_priv();
+	
 	e = gfarmfs_init();
 	while (e == NULL) {
 		gf = (GFS_File) fi->fh;
@@ -951,18 +1104,23 @@
 		break;
 	}
 
-	return gfarmfs_final(e, n, path);
+	retval = gfarmfs_final(e, n, path);
+	unset_priv();
+	
+	return retval;
 }
 
 static int
 gfarmfs_write(const char *path, const char *buf, size_t size,
 	      off_t offset, struct fuse_file_info *fi)
 {
-	int n;
+	int n, retval;
 	file_offset_t off;
 	char *e;
 	GFS_File gf;
 
+	set_priv();
+	
 	e = gfarmfs_init();
 	while (e == NULL) {
 		gf = (GFS_File) fi->fh;
@@ -972,7 +1130,10 @@
 		break;
 	}
 
-	return gfarmfs_final(e, n, path);
+	retval = gfarmfs_final(e, n, path);
+	unset_priv();
+	
+	return retval;
 }
 
 #if 0
@@ -1093,8 +1254,17 @@
 	int i;
 	int ok_s = 0; /* check -s */
 	char *opt_s_str = "-s";
+	int fuse_opt = 0;
+	char * fuse_args = NULL, * new_fuse_args = NULL, * tmp_fuse_args = NULL;
+	int fuse_opt_idx = -1;
+	int map_home = 0;
 
 	for(i = 1; i < argc; i++) {
+		if(fuse_opt) {
+			fuse_args = argv[i];
+			fuse_opt = 0;
+			continue;
+		}
 		if (strcmp(argv[i], "-s") == 0) {
 			ok_s = 1;
 		} else if (strcmp(argv[i], "-f") == 0) {
@@ -1104,10 +1274,89 @@
 		} else if (strcmp(argv[i], "-h") == 0) {
 			gfarmfs_usage();
 			exit(0);
+		} else if (strcmp(argv[i], "-o") == 0) {
+			fuse_opt = 1;
+			fuse_opt_idx = i;
+		}
+	}
+	if(fuse_args) {
+		char * tok = NULL;
+		char * cur = fuse_args;
+		char * user, * group;
+		uid_t tmp_uid;
+		gid_t tmp_gid;
+		struct passwd * pwd;
+		struct group * gr;
+		size_t arg_len = strlen(fuse_args) + 1;
+		int num_opt = 0;
+
+		new_fuse_args = (char *)malloc(arg_len * sizeof(char));
+		if(new_fuse_args == NULL) {
+			return;
+		}
+		tmp_fuse_args = new_fuse_args;
+		tok = strchr(cur, ',');
+		while( (tok != NULL) || ((tok == NULL) && ( (*cur) != '\0'))) {
+			if(tok != NULL) (*tok) = '\0';
+			if(strstr(cur, "map_home") == cur) {
+				map_home = 1;
+				num_opt++;
+			} else if(strstr(cur, "uid=") == cur) {
+				tmp_uid = (uid_t)strtoul(&cur[4], &user, 10);
+				if( ((*user) != '\0') && (pwd = getpwnam(&cur[4]))) {
+					/* we got user name instead */
+					tmp_uid = pwd->pw_uid;
+				}
+				gfarm_run_uid = tmp_uid;
+				enable_priv = 1;
+				snprintf(tmp_fuse_args, arg_len, "uid=%d,", tmp_uid);
+				tmp_fuse_args += strlen(tmp_fuse_args);
+				num_opt++;
+			} else if(strstr(cur, "gid=") == cur) {
+				tmp_gid = (gid_t)strtoul(&cur[4], &group, 10);
+				if( ((*group) != '\0') && (gr = getgrnam(&cur[4]))) {
+					/* we got user name instead */
+					tmp_gid = gr->gr_gid;
+				}
+				gfarm_run_gid = tmp_gid;
+				enable_priv = 1;
+				snprintf(tmp_fuse_args, arg_len, "gid=%d,", tmp_gid);
+				tmp_fuse_args += strlen(tmp_fuse_args);
+				num_opt++;
+			} else {
+				if(tok != NULL) (*tok) = '\0';
+				snprintf(tmp_fuse_args, arg_len, "%s,", cur);
+				tmp_fuse_args += strlen(tmp_fuse_args);
+				if(tok != NULL) (*tok) = ',';
+				num_opt++;
+			}
+			if(tok != NULL) {
+				(*tok) = ',';
+				cur = ++tok;
+				tok = strchr(cur, ',');
+			} else {
+				break;
+			}
+		}
+		if(map_home) {
+			if( (pwd = getpwuid(gfarm_run_uid)) != NULL) {
+				home_dir = strdup(pwd->pw_name);
+			}
+		}
+		new_fuse_args[strlen(new_fuse_args) - 1] = '\0';
+		/* assume here that fuse args is always shorter than new args */
+		strcpy(fuse_args, new_fuse_args);
+		if( (num_opt == 1) && home_dir) {
+			/* map_home is an invalid option for fuse, discard it */
+			for(i = (fuse_opt_idx + 2); i < argc; i++) {
+				argv[i-2] = argv[i];
+			}
+			argc -= 2;
+			(*argcp) = argc;
 		}
 	}
 	if (ok_s == 0) { /* add -s option */
-		newargv = malloc((argc + 1) * sizeof(char *));
+		newargv = calloc((argc + 1), sizeof(char *));
 		for (i = 0; i < argc; i++) {
 			newargv[i] = argv[i];
 		}
@@ -1176,19 +1425,35 @@
 	int ret;
 	char *e;
 
+	/* initialize privileges */
+	gfarm_run_uid = geteuid();
+	gfarm_run_gid = getegid();
+	old_uid = geteuid();
+	old_gid = getegid();
+
 	if (argc > 0) {
 		program_name = basename(argv[0]);
 	}
+	check_gfarmfs_options(&argc, &argv);
+	/* gfarm uid/gid might be changed by fuse option */
+	check_fuse_options(&argc, &argv);
+	/* Only allow uid change if we run by root */
+	if(geteuid() == 0) {
+		set_priv();
+	} else {
+		gfarm_run_uid = geteuid();
+		gfarm_run_gid = getegid();
+	}
 	/* e = gfarm_initialize(&argc, &argv); */
 	e = gfarm_initialize(NULL, NULL);
+	unset_priv();
 	if (e != NULL) {
 		fprintf(stderr, "%s: %s\n", program_name, e);
 		exit(-1);
 	}
-	check_gfarmfs_options(&argc, &argv);
-	check_fuse_options(&argc, &argv);
 
 	ret = fuse_main(argc, argv, &gfarmfs_oper);
 	gfarmfs_fastcreate_check();
+	if(home_dir != NULL) free(home_dir);
 	return (ret);
 }