return ctxt->uid == 0;
}
+static inline int want_check_owner(struct fuse2fs *ff,
+ struct fuse_context *ctxt)
+{
+ /*
+ * The kernel is responsible for access control, so we allow anything
+ * that the superuser can do.
+ */
+ if (ff->kernel)
+ return 0;
+ return !is_superuser(ff, ctxt);
+}
+
static int check_inum_access(ext2_filsys fs, ext2_ino_t ino, mode_t mask)
{
struct fuse_context *ctxt = fuse_get_context();
(inode.i_flags & EXT2_IMMUTABLE_FL))
return -EACCES;
+ /* If kernel is responsible for mode and acl checks, we're done. */
+ if (ff->kernel)
+ return 0;
+
/* Figure out what root's allowed to do */
if (is_superuser(ff, ctxt)) {
/* Non-file access always ok */
goto out;
}
- if (!is_superuser(ff, ctxt) && ctxt->uid != inode_uid(inode)) {
+ if (want_check_owner(ff, ctxt) && ctxt->uid != inode_uid(inode)) {
ret = -EPERM;
goto out;
}
/* FUSE seems to feed us ~0 to mean "don't change" */
if (owner != (uid_t) ~0) {
/* Only root gets to change UID. */
- if (!is_superuser(ff, ctxt) &&
+ if (want_check_owner(ff, ctxt) &&
!(inode_uid(inode) == ctxt->uid && owner == ctxt->uid)) {
ret = -EPERM;
goto out;
if (group != (gid_t) ~0) {
/* Only root or the owner get to change GID. */
- if (!is_superuser(ff, ctxt) &&
+ if (want_check_owner(ff, ctxt) &&
inode_uid(inode) != ctxt->uid) {
ret = -EPERM;
goto out;
if (err)
return translate_error(fs, fh->ino, err);
- if (!is_superuser(ff, ctxt) && inode_uid(inode) != ctxt->uid)
+ if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
return -EPERM;
ret = set_iflags(&inode, flags);
if (err)
return translate_error(fs, fh->ino, err);
- if (!is_superuser(ff, ctxt) && inode_uid(inode) != ctxt->uid)
+ if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
return -EPERM;
inode.i_generation = generation;
if (err)
return translate_error(fs, fh->ino, err);
- if (!is_superuser(ff, ctxt) && inode_uid(inode) != ctxt->uid)
+ if (want_check_owner(ff, ctxt) && inode_uid(inode) != ctxt->uid)
return -EPERM;
ret = set_iflags(&inode, flags);