From: Miklos S. <mi...@sz...> - 2012-09-13 10:27:05
|
Alkis Georgopoulos <al...@gm...> writes: > Hi, SSHFS returns "writeable, executable" even for files that lack those > attributes: > > $ mkdir /tmp/etc > $ sshfs localhost:/etc /tmp/etc > > $ strace gvfs-info /etc/login.defs 2>&1 | grep '^access.*login.defs' > access("/etc/login.defs", R_OK) = 0 > access("/etc/login.defs", W_OK) = -1 EACCES (Permission denied) > access("/etc/login.defs", X_OK) = -1 EACCES (Permission denied) > > $ strace gvfs-info /tmp/etc/login.defs 2>&1 | grep '^access.*login.defs' > access("/tmp/etc/login.defs", R_OK) = 0 > access("/tmp/etc/login.defs", W_OK) = 0 > access("/tmp/etc/login.defs", X_OK) = 0 > > > This e.g. makes nautilus try to execute text files on sshfs mounts: > https://bugzilla.gnome.org/show_bug.cgi?id=679187 > https://bugs.launchpad.net/ubuntu/+source/sshfs-fuse/+bug/1017870 Okay, following patch for sshfs should fix the X_OK access. Read and write access cannot be determined from just the mode bits. Thanks, Miklos diff --git a/cache.c b/cache.c index 2a06726..6e93157 100644 --- a/cache.c +++ b/cache.c @@ -490,6 +490,7 @@ static void cache_unity_fill(struct fuse_cache_operations *oper, cache_oper->init = oper->oper.init; #endif cache_oper->getattr = oper->oper.getattr; + cache_oper->access = oper->oper.access; cache_oper->readlink = oper->oper.readlink; cache_oper->getdir = cache_unity_getdir; cache_oper->mknod = oper->oper.mknod; diff --git a/sshfs.c b/sshfs.c index 4945302..e663c2f 100644 --- a/sshfs.c +++ b/sshfs.c @@ -247,6 +247,7 @@ struct sshfs { int ext_statvfs; int ext_hardlink; mode_t mnt_mode; + struct fuse_operations *op; /* statistics */ uint64_t bytes_sent; @@ -1915,6 +1916,22 @@ static int sshfs_getattr(const char *path, struct stat *stbuf) return err; } +static int sshfs_access(const char *path, int mask) +{ + struct stat stbuf; + int err = 0; + + if (mask & X_OK) { + err = sshfs.op->getattr(path, &stbuf); + if (!err) { + if (S_ISREG(stbuf.st_mode) && + !(stbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) + err = -EACCES; + } + } + return err; +} + static int count_components(const char *p) { int ctr; @@ -3115,6 +3132,7 @@ static struct fuse_cache_operations sshfs_oper = { .oper = { .init = sshfs_init, .getattr = sshfs_getattr, + .access = sshfs_access, .readlink = sshfs_readlink, .mknod = sshfs_mknod, .mkdir = sshfs_mkdir, @@ -3215,10 +3233,11 @@ static int is_ssh_opt(const char *arg) static int sshfs_fuse_main(struct fuse_args *args) { + sshfs.op = cache_init(&sshfs_oper); #if FUSE_VERSION >= 26 - return fuse_main(args->argc, args->argv, cache_init(&sshfs_oper), NULL); + return fuse_main(args->argc, args->argv, sshfs.op, NULL); #else - return fuse_main(args->argc, args->argv, cache_init(&sshfs_oper)); + return fuse_main(args->argc, args->argv, sshfs.op); #endif } @@ -3856,7 +3875,8 @@ int main(int argc, char *argv[]) if (res == -1) perror("WARNING: failed to set FD_CLOEXEC on fuse device"); - fuse = fuse_new(ch, &args, cache_init(&sshfs_oper), + sshfs.op = cache_init(&sshfs_oper); + fuse = fuse_new(ch, &args, sshfs.op, sizeof(struct fuse_operations), NULL); if (fuse == NULL) { fuse_unmount(mountpoint, ch); |