コード例 #1
0
ファイル: inode.c プロジェクト: rhamilton1415/steamlink-sdk
/*
 * This is a variant of fs/namei.c:permission() or inode_permission() which
 * skips over EROFS tests (because we perform copyup on EROFS).
 */
static int __inode_permission(struct inode *inode, int mask)
{
	int retval;

	/* nobody gets write access to an immutable file */
	if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
		return -EACCES;

	/* Ordinary permission routines do not understand MAY_APPEND. */
	if (inode->i_op && inode->i_op->permission) {
		retval = inode->i_op->permission(inode, mask);
		if (!retval) {
			/*
			 * Exec permission on a regular file is denied if none
			 * of the execute bits are set.
			 *
			 * This check should be done by the ->permission()
			 * method.
			 */
			if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
			    !(inode->i_mode & S_IXUGO))
				return -EACCES;
		}
	} else {
		retval = generic_permission(inode, mask);
	}
	if (retval)
		return retval;

	return security_inode_permission(inode,
			mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
}
コード例 #2
0
ファイル: i_op.c プロジェクト: ammubhave/bargud
static int h_permission(struct inode *h_inode, int mask,
			struct vfsmount *h_mnt, int brperm)
{
	int err;
	const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));

	err = -EACCES;
	if ((write_mask && IS_IMMUTABLE(h_inode))
	    || ((mask & MAY_EXEC)
		&& S_ISREG(h_inode->i_mode)
		&& ((h_mnt->mnt_flags & MNT_NOEXEC)
		    || !(h_inode->i_mode & S_IXUGO))))
		goto out;

	/*
	 * - skip the lower fs test in the case of write to ro branch.
	 * - nfs dir permission write check is optimized, but a policy for
	 *   link/rename requires a real check.
	 * - nfs always sets MS_POSIXACL regardless its mount option 'noacl.'
	 *   in this case, generic_permission() returns -EOPNOTSUPP.
	 */
	if ((write_mask && !au_br_writable(brperm))
	    || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
		&& write_mask && !(mask & MAY_READ))
	    || !h_inode->i_op->permission) {
		/* AuLabel(generic_permission); */
		/* AuDbg("get_acl %pf\n", h_inode->i_op->get_acl); */
		err = generic_permission(h_inode, mask);
		if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
			err = h_inode->i_op->permission(h_inode, mask);
		AuTraceErr(err);
	} else {
		/* AuLabel(h_inode->permission); */
		err = h_inode->i_op->permission(h_inode, mask);
		AuTraceErr(err);
	}

	if (!err)
		err = devcgroup_inode_permission(h_inode, mask);
	if (!err)
		err = security_inode_permission(h_inode, mask);

#if 0
	if (!err) {
		/* todo: do we need to call ima_path_check()? */
		struct path h_path = {
			.dentry	=
			.mnt	= h_mnt
		};
		err = ima_path_check(&h_path,
				     mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
				     IMA_COUNT_LEAVE);
	}
#endif

out:
	return err;
}
コード例 #3
0
ファイル: handle_ioctl.c プロジェクト: alangenfeld/cloud-nfs
int handle_permission(struct inode *inode, int mask)
{
	int submask;
	umode_t mode = inode->i_mode;

	if (mask & MAY_WRITE) {

		/*
		 * Nobody gets write access to a read-only fs.
		 */
		if (IS_RDONLY(inode) &&
		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
			return -EROFS;

		/*
		 * Nobody gets write access to an immutable file.
		 */
		if (IS_IMMUTABLE(inode))
			return -EACCES;
	}

	/*
	 * MAY_EXEC on regular files requires special handling: We override
	 * filesystem execute permissions if the mode bits aren't set.
	 */
	if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
		return -EACCES;

	/* Ordinary permission routines do not understand MAY_APPEND. */
	submask = mask & ~MAY_APPEND;
#ifdef IN_KERNEL_CHANGE_NOT_SUPP

	/* FIXME! we don't have nameidata for handle lookup. So not sure how
         * we can check for inode->permissions. We already limit the call
         * to CAP_DAC_OVERRIDE. So we should be able to skip the ACL check.
         * But we also skip security_inode_permission below.
         */

	if (inode->i_op && inode->i_op->permission)
		retval = inode->i_op->permission(inode, submask, nd);
	else
		retval = generic_permission(inode, submask, NULL);
	if (retval)
		return retval;

	return security_inode_permission(inode, mask, nd);
#else
        return generic_permission(inode, submask, NULL);
#endif

}
コード例 #4
0
/* Basically copied from the kernel vfs permission(), but we've changed
 * the following: (1) the IS_RDONLY check is skipped, and (2) if you set
 * the mount option `nfsperms=insceure', we assume that -EACCES means that
 * the export is read-only and we should check standard Unix permissions.
 * This means that NFS ACL checks (or other advanced permission features)
 * are bypassed.
 */
static int inode_permission(struct inode *inode, int mask, struct nameidata *nd,
			    int bindex)
{
	int retval, submask;

	if (mask & MAY_WRITE) {
		/* The first branch is allowed to be really readonly. */
		if (bindex == 0) {
			umode_t mode = inode->i_mode;
			if (IS_RDONLY(inode) && (S_ISREG(mode) || S_ISDIR(mode)
						 || S_ISLNK(mode)))
				return -EROFS;
		}
		/*
		 * Nobody gets write access to an immutable file.
		 */
		if (IS_IMMUTABLE(inode))
			return -EACCES;
	}

	/* Ordinary permission routines do not understand MAY_APPEND. */
	submask = mask & ~MAY_APPEND;
	if (inode->i_op && inode->i_op->permission) {
		retval = inode->i_op->permission(inode, submask, nd);
		if ((retval == -EACCES) && (submask & MAY_WRITE) &&
		    (!strcmp("nfs", (inode)->i_sb->s_type->name)) &&
		    (nd) && (nd->mnt) && (nd->mnt->mnt_sb) &&
		    (branchperms(nd->mnt->mnt_sb, bindex) & MAY_NFSRO)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
			retval = vfs_permission(inode, submask);
#else
			retval = generic_permission(inode, submask, NULL);
#endif
		}
	} else {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
		retval = vfs_permission(inode, submask);
#else
		retval = generic_permission(inode, submask, NULL);
#endif
	}
	
	if (retval && retval != -EROFS) /* ignore EROFS */
		return retval;

	retval = security_inode_permission(inode, mask, nd);
	return ((retval == -EROFS) ? 0 : retval); /* ignore EROFS */
}
コード例 #5
0
ファイル: inode.c プロジェクト: jue-jiang/rc3-linux
int ovl_permission(struct inode *inode, int mask)
{
	struct ovl_entry *oe;
	struct dentry *alias = NULL;
	struct inode *realinode;
	struct dentry *realdentry;
	bool is_upper;
	int err;

	if (S_ISDIR(inode->i_mode)) {
		oe = inode->i_private;
	} else if (mask & MAY_NOT_BLOCK) {
		return -ECHILD;
	} else {
		/*
		 * For non-directories find an alias and get the info
		 * from there.
		 */
		spin_lock(&inode->i_lock);
		if (WARN_ON(list_empty(&inode->i_dentry))) {
			spin_unlock(&inode->i_lock);
			return -ENOENT;
		}
		alias = list_entry(inode->i_dentry.next,
				   struct dentry, d_alias);
		dget(alias);
		spin_unlock(&inode->i_lock);
		oe = alias->d_fsdata;
	}

	realdentry = ovl_entry_real(oe, &is_upper);

	/* Careful in RCU walk mode */
	realinode = ACCESS_ONCE(realdentry->d_inode);
	if (!realinode) {
		WARN_ON(!(mask & MAY_NOT_BLOCK));
		err = -ENOENT;
		goto out_dput;
	}

	if (mask & MAY_WRITE) {
		umode_t mode = realinode->i_mode;

		/*
		 * Writes will always be redirected to upper layer, so
		 * ignore lower layer being read-only.
		 *
		 * If the overlay itself is read-only then proceed
		 * with the permission check, don't return EROFS.
		 * This will only happen if this is the lower layer of
		 * another overlayfs.
		 *
		 * If upper fs becomes read-only after the overlay was
		 * constructed return EROFS to prevent modification of
		 * upper layer.
		 */
		err = -EROFS;
		if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
			goto out_dput;

		/*
		 * Nobody gets write access to an immutable file.
		 */
		err = -EACCES;
		if (IS_IMMUTABLE(realinode))
			goto out_dput;
	}

	if (realinode->i_op->permission)
		err = realinode->i_op->permission(realinode, mask);
	else
		err = generic_permission(realinode, mask);

	if (!err)
		err = devcgroup_inode_permission(realinode, mask);
	if (!err)
		err = security_inode_permission(realinode, mask);
out_dput:
	dput(alias);
	return err;
}