@@ -122,6 +122,7 @@ struct lo_inode {
struct lo_cred {
uid_t euid;
gid_t egid;
+ mode_t umask;
};
enum {
@@ -172,6 +173,8 @@ struct lo_data {
/* An O_PATH file descriptor to /proc/self/fd/ */
int proc_self_fd;
int user_killpriv_v2, killpriv_v2;
+ /* If set, virtiofsd is responsible for setting umask during creation */
+ bool change_umask;
};
static const struct fuse_opt lo_opts[] = {
@@ -1134,7 +1137,8 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
* ownership of caller.
* TODO: What about selinux context?
*/
-static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
+static int lo_change_cred(fuse_req_t req, struct lo_cred *old,
+ bool change_umask)
{
int res;
@@ -1154,11 +1158,14 @@ static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
return errno_save;
}
+ if (change_umask) {
+ old->umask = umask(req->ctx.umask);
+ }
return 0;
}
/* Regain Privileges */
-static void lo_restore_cred(struct lo_cred *old)
+static void lo_restore_cred(struct lo_cred *old, bool restore_umask)
{
int res;
@@ -1173,6 +1180,9 @@ static void lo_restore_cred(struct lo_cred *old)
fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid);
exit(1);
}
+
+ if (restore_umask)
+ umask(old->umask);
}
static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
@@ -1202,7 +1212,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
return;
}
- saverr = lo_change_cred(req, &old);
+ saverr = lo_change_cred(req, &old, lo->change_umask && !S_ISLNK(mode));
if (saverr) {
goto out;
}
@@ -1211,7 +1221,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
saverr = errno;
- lo_restore_cred(&old);
+ lo_restore_cred(&old, lo->change_umask && !S_ISLNK(mode));
if (res == -1) {
goto out;
@@ -1917,7 +1927,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
return;
}
- err = lo_change_cred(req, &old);
+ err = lo_change_cred(req, &old, lo->change_umask);
if (err) {
goto out;
}
@@ -1928,7 +1938,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
err = fd == -1 ? errno : 0;
- lo_restore_cred(&old);
+ lo_restore_cred(&old, lo->change_umask);
/* Ignore the error if file exists and O_EXCL was not given */
if (err && (err != EEXIST || (fi->flags & O_EXCL))) {