From: Miklos Szeredi Date: Sun, 30 Jul 2006 17:33:40 +0000 (+0000) Subject: fixes X-Git-Tag: fuse_2_6_0_rc1~13 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=9a5c11d132298239be66d7538c3f8c6b03f8ad95;p=qemu-gpiodev%2Flibfuse.git fixes --- diff --git a/ChangeLog b/ChangeLog index cd91c20..b7105be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,22 @@ +2006-07-30 Miklos Szeredi + + * fusermount: if selinux is active, restore the original file's + security context in unmount_rename(). Redhat bugzilla id 188561. + Patch from Yves Perrenoud + + * Add POSIX file locking operation to high level library + +2006-07-14 Miklos Szeredi + + * Multiple release() calls can race with each other, resulting in + the hidden file being deleted before the last release finishes. + Bug found and patch tested by Mark Huijgen + 2006-07-05 Miklos Szeredi - * fusermount: if /dev/fuse doesn't exist, suggest moddprobing - fuse; this makes sense on systems using udev. Reported by - Szakacsits Szabolcs + * fusermount: if /dev/fuse doesn't exist, suggest modprobing fuse; + this makes sense on systems using udev. Reported by Szakacsits + Szabolcs 2006-06-29 Miklos Szeredi diff --git a/configure.in b/configure.in index 91b65b1..063f68f 100644 --- a/configure.in +++ b/configure.in @@ -3,9 +3,7 @@ AC_CANONICAL_TARGET AM_INIT_AUTOMAKE AM_CONFIG_HEADER(include/config.h) -m4_ifdef([LT_INIT], - [LT_INIT], - [AC_PROG_LIBTOOL]) +AC_PROG_LIBTOOL AC_PROG_CC # compatibility for automake < 1.8 @@ -84,5 +82,7 @@ AC_SUBST(subdirs2) AM_CONDITIONAL(LINUX, test "$arch" = linux) AM_CONDITIONAL(BSD, test "$arch" = bsd) +AC_CHECK_HEADERS(selinux/selinux.h, AC_CHECK_LIB(selinux, getfilecon)) + AC_CONFIG_FILES([fuse.pc Makefile lib/Makefile util/Makefile example/Makefile include/Makefile]) AC_OUTPUT diff --git a/include/fuse.h b/include/fuse.h index fe52531..ad2ef00 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -22,10 +22,11 @@ #include "fuse_common.h" +#include +#include #include #include #include -#include #ifdef __cplusplus extern "C" { @@ -361,6 +362,9 @@ struct fuse_operations { * Introduced in version 2.5 */ int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); + + int (*lock) (const char *, struct fuse_file_info *, int cmd, + struct flock *, uint64_t owner); }; /** Extra context that may be needed by some filesystems diff --git a/lib/fuse.c b/lib/fuse.c index 2fc6fa4..4f7a175 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -1312,7 +1312,6 @@ static void fuse_flush(fuse_req_t req, fuse_ino_t ino, char *path; int err; - (void) owner; err = -ENOENT; pthread_rwlock_rdlock(&f->tree_lock); path = get_path(f, ino); @@ -1326,6 +1325,15 @@ static void fuse_flush(fuse_req_t req, fuse_ino_t ino, err = f->op.flush(path, fi); free(path); } + if (f->op.lock) { + struct flock lock; + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + f->op.lock(path, fi, F_SETLK, &lock, owner); + if (err == -ENOSYS) + err = 0; + } pthread_rwlock_unlock(&f->tree_lock); reply_err(req, err); } @@ -1339,13 +1347,6 @@ static void fuse_release(fuse_req_t req, fuse_ino_t ino, int unlink_hidden; pthread_rwlock_rdlock(&f->tree_lock); - pthread_mutex_lock(&f->lock); - node = get_node(f, ino); - assert(node->open_count > 0); - --node->open_count; - unlink_hidden = (node->is_hidden && !node->open_count); - pthread_mutex_unlock(&f->lock); - path = get_path(f, ino); if (f->conf.debug) { printf("RELEASE[%llu] flags: 0x%x\n", (unsigned long long) fi->fh, @@ -1355,6 +1356,13 @@ static void fuse_release(fuse_req_t req, fuse_ino_t ino, if (f->op.release) fuse_do_release(f, path, fi); + pthread_mutex_lock(&f->lock); + node = get_node(f, ino); + assert(node->open_count > 0); + --node->open_count; + unlink_hidden = (node->is_hidden && !node->open_count); + pthread_mutex_unlock(&f->lock); + if(unlink_hidden && path) f->op.unlink(path); @@ -1809,6 +1817,44 @@ static void fuse_removexattr(fuse_req_t req, fuse_ino_t ino, const char *name) reply_err(req, err); } +static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock, + uint64_t owner, int cmd) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = -ENOENT; + pthread_rwlock_rdlock(&f->tree_lock); + path = get_path(f, ino); + if (path != NULL) { + err = f->op.lock(path, fi, cmd, lock, owner); + free(path); + } + pthread_rwlock_unlock(&f->tree_lock); + return err; +} + +static void fuse_getlk(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock, + uint64_t owner) +{ + int err = fuse_lock_common(req, ino, fi, lock, owner, F_GETLK); + if (!err) + fuse_reply_lock(req, lock); + else + reply_err(req, err); +} + +static void fuse_setlk(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock, + uint64_t owner, int sleep) +{ + reply_err(req, fuse_lock_common(req, ino, fi, lock, owner, + sleep ? F_SETLKW : F_SETLK)); +} + static struct fuse_lowlevel_ops fuse_path_ops = { .init = fuse_data_init, .destroy = fuse_data_destroy, @@ -1841,6 +1887,8 @@ static struct fuse_lowlevel_ops fuse_path_ops = { .getxattr = fuse_getxattr, .listxattr = fuse_listxattr, .removexattr = fuse_removexattr, + .getlk = fuse_getlk, + .setlk = fuse_setlk, }; static void free_cmd(struct fuse_cmd *cmd) @@ -2011,6 +2059,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, { struct fuse *f; struct node *root; + struct fuse_lowlevel_ops llop = fuse_path_ops; if (sizeof(struct fuse_operations) < op_size) { fprintf(stderr, "fuse: warning: library too old, some operations may not not work\n"); @@ -2047,8 +2096,13 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, goto out_free; } - f->se = fuse_lowlevel_new_common(args, &fuse_path_ops, - sizeof(fuse_path_ops), f); + memcpy(&f->op, op, op_size); + if (!f->op.lock) { + llop.getlk = NULL; + llop.setlk = NULL; + } + + f->se = fuse_lowlevel_new_common(args, &llop,sizeof(llop), f); if (f->se == NULL) goto out_free; @@ -2075,7 +2129,6 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, mutex_init(&f->lock); pthread_rwlock_init(&f->tree_lock, NULL); - memcpy(&f->op, op, op_size); f->compat = compat; root = (struct node *) calloc(1, sizeof(struct node)); diff --git a/util/fusermount.c b/util/fusermount.c index 4a3c264..6d3ef97 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -39,6 +39,10 @@ #include #include +#ifdef HAVE_SELINUX_SELINUX_H +#include +#endif + #define FUSE_COMMFD_ENV "_FUSE_COMMFD" #define FUSE_DEV_OLD "/proc/fs/fuse/dev" @@ -185,6 +189,18 @@ static int unmount_rename(const char *mtab, const char *mtab_new) if (stat(mtab, &sbuf) == 0) chown(mtab_new, sbuf.st_uid, sbuf.st_gid); +#ifdef HAVE_LIBSELINUX + { + security_context_t filecon; + + if (getfilecon(mtab, &filecon) > 0) { + setfilecon(mtab_new, filecon); + if (filecon != NULL) + freecon(filecon); + } + } +#endif + res = rename(mtab_new, mtab); if (res == -1) { fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,