|
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:
-- ----------------------------------------------------------------------------------- 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);
}