Skip to content

Commit b138777

Browse files
davemarchevskyMiklos Szeredi
authored andcommitted
fuse: Rearrange fuse_allow_current_process checks
This is a followup to a previous commit of mine [0], which added the allow_sys_admin_access && capable(CAP_SYS_ADMIN) check. This patch rearranges the order of checks in fuse_allow_current_process without changing functionality. Commit 9ccf47b ("fuse: Add module param for CAP_SYS_ADMIN access bypassing allow_other") added allow_sys_admin_access && capable(CAP_SYS_ADMIN) check to the beginning of the function, with the reasoning that allow_sys_admin_access should be an 'escape hatch' for users with CAP_SYS_ADMIN, allowing them to skip any subsequent checks. However, placing this new check first results in many capable() calls when allow_sys_admin_access is set, where another check would've also returned 1. This can be problematic when a BPF program is tracing capable() calls. At Meta we ran into such a scenario recently. On a host where allow_sys_admin_access is set but most of the FUSE access is from processes which would pass other checks - i.e. they don't need CAP_SYS_ADMIN 'escape hatch' - this results in an unnecessary capable() call for each fs op. We also have a daemon tracing capable() with BPF and doing some data collection, so tracing these extraneous capable() calls has the potential to regress performance for an application doing many FUSE ops. So rearrange the order of these checks such that CAP_SYS_ADMIN 'escape hatch' is checked last. Add a small helper, fuse_permissible_uidgid, to make the logic easier to understand. Previously, if allow_other is set on the fuse_conn, uid/git checking doesn't happen as current_in_userns result is returned. These semantics are maintained here: fuse_permissible_uidgid check only happens if allow_other is not set. Signed-off-by: Dave Marchevsky <[email protected]> Suggested-by: Andrii Nakryiko <[email protected]> Reviewed-by: Christian Brauner (Microsoft) <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 1535240 commit b138777

File tree

2 files changed

+21
-16
lines changed

2 files changed

+21
-16
lines changed

fs/fuse/dir.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,18 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
12371237
return err;
12381238
}
12391239

1240+
static inline bool fuse_permissible_uidgid(struct fuse_conn *fc)
1241+
{
1242+
const struct cred *cred = current_cred();
1243+
1244+
return (uid_eq(cred->euid, fc->user_id) &&
1245+
uid_eq(cred->suid, fc->user_id) &&
1246+
uid_eq(cred->uid, fc->user_id) &&
1247+
gid_eq(cred->egid, fc->group_id) &&
1248+
gid_eq(cred->sgid, fc->group_id) &&
1249+
gid_eq(cred->gid, fc->group_id));
1250+
}
1251+
12401252
/*
12411253
* Calling into a user-controlled filesystem gives the filesystem
12421254
* daemon ptrace-like capabilities over the current process. This
@@ -1250,26 +1262,19 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
12501262
* for which the owner of the mount has ptrace privilege. This
12511263
* excludes processes started by other users, suid or sgid processes.
12521264
*/
1253-
int fuse_allow_current_process(struct fuse_conn *fc)
1265+
bool fuse_allow_current_process(struct fuse_conn *fc)
12541266
{
1255-
const struct cred *cred;
1256-
1257-
if (allow_sys_admin_access && capable(CAP_SYS_ADMIN))
1258-
return 1;
1267+
bool allow;
12591268

12601269
if (fc->allow_other)
1261-
return current_in_userns(fc->user_ns);
1270+
allow = current_in_userns(fc->user_ns);
1271+
else
1272+
allow = fuse_permissible_uidgid(fc);
12621273

1263-
cred = current_cred();
1264-
if (uid_eq(cred->euid, fc->user_id) &&
1265-
uid_eq(cred->suid, fc->user_id) &&
1266-
uid_eq(cred->uid, fc->user_id) &&
1267-
gid_eq(cred->egid, fc->group_id) &&
1268-
gid_eq(cred->sgid, fc->group_id) &&
1269-
gid_eq(cred->gid, fc->group_id))
1270-
return 1;
1274+
if (!allow && allow_sys_admin_access && capable(CAP_SYS_ADMIN))
1275+
allow = true;
12711276

1272-
return 0;
1277+
return allow;
12731278
}
12741279

12751280
static int fuse_access(struct inode *inode, int mask)

fs/fuse/fuse_i.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ bool fuse_invalid_attr(struct fuse_attr *attr);
11791179
/**
11801180
* Is current process allowed to perform filesystem operation?
11811181
*/
1182-
int fuse_allow_current_process(struct fuse_conn *fc);
1182+
bool fuse_allow_current_process(struct fuse_conn *fc);
11831183

11841184
u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
11851185

0 commit comments

Comments
 (0)