return 0;
}
+/*
+ * get the security ID of a set of credentials
+ */
+static inline u32 cred_sid(const struct cred *cred)
+{
+ const struct task_security_struct *tsec;
+
+ tsec = cred->security;
+ return tsec->sid;
+}
+
/*
* get the security ID of a task
*/
static inline u32 task_sid(const struct task_struct *task)
{
- const struct task_security_struct *tsec;
u32 sid;
rcu_read_lock();
- tsec = __task_cred(task)->security;
- sid = tsec->sid;
+ sid = cred_sid(__task_cred(task));
rcu_read_unlock();
return sid;
}
return tsec->sid;
}
+/* Allocate and free functions for each kind of security blob. */
+
static int inode_alloc_security(struct inode *inode)
{
struct inode_security_struct *isec;
}
/*
- * Check permission betweeen a pair of tasks, e.g. signal checks,
+ * Check permission between a pair of tasks, e.g. signal checks,
* fork check, ptrace check, etc.
* tsk1 is the actor and tsk2 is the target
*/
/* Check whether a task has a particular permission to an inode.
The 'adp' parameter is optional and allows other audit
data to be passed (e.g. the dentry). */
-static int inode_has_perm(struct task_struct *tsk,
+static int inode_has_perm(const struct cred *cred,
struct inode *inode,
u32 perms,
struct avc_audit_data *adp)
if (unlikely(IS_PRIVATE(inode)))
return 0;
- sid = task_sid(tsk);
+ sid = cred_sid(cred);
isec = inode->i_security;
if (!adp) {
/* Same as inode_has_perm, but pass explicit audit data containing
the dentry to help the auditing code to more easily generate the
pathname if needed. */
-static inline int dentry_has_perm(struct task_struct *tsk,
+static inline int dentry_has_perm(const struct cred *cred,
struct vfsmount *mnt,
struct dentry *dentry,
u32 av)
{
struct inode *inode = dentry->d_inode;
struct avc_audit_data ad;
+
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.mnt = mnt;
ad.u.fs.path.dentry = dentry;
- return inode_has_perm(tsk, inode, av, &ad);
+ return inode_has_perm(cred, inode, av, &ad);
}
/* Check whether a task can use an open file descriptor to
has the same SID as the process. If av is zero, then
access to the file is not checked, e.g. for cases
where only the descriptor is affected like seek. */
-static int file_has_perm(struct task_struct *tsk,
- struct file *file,
- u32 av)
+static int file_has_perm(const struct cred *cred,
+ struct file *file,
+ u32 av)
{
struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode;
struct avc_audit_data ad;
- u32 sid = task_sid(tsk);
+ u32 sid = cred_sid(cred);
int rc;
AVC_AUDIT_DATA_INIT(&ad, FS);
FD__USE,
&ad);
if (rc)
- return rc;
+ goto out;
}
/* av is zero if only checking access to the descriptor. */
+ rc = 0;
if (av)
- return inode_has_perm(tsk, inode, av, &ad);
+ rc = inode_has_perm(cred, inode, av, &ad);
- return 0;
+out:
+ return rc;
}
/* Check whether a task can create a file. */
}
/* Check whether a task can perform a filesystem operation. */
-static int superblock_has_perm(struct task_struct *tsk,
+static int superblock_has_perm(const struct cred *cred,
struct super_block *sb,
u32 perms,
struct avc_audit_data *ad)
{
struct superblock_security_struct *sbsec;
- u32 sid = task_sid(tsk);
+ u32 sid = cred_sid(cred);
sbsec = sb->s_security;
return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
{
+ const struct cred *cred = current_cred();
int rc = 0;
if (!sb)
case Q_QUOTAOFF:
case Q_SETINFO:
case Q_SETQUOTA:
- rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
- NULL);
+ rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
break;
case Q_GETFMT:
case Q_GETINFO:
case Q_GETQUOTA:
- rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
- NULL);
+ rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
break;
default:
rc = 0; /* let the kernel handle invalid cmds */
static int selinux_quota_on(struct dentry *dentry)
{
- return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
+ const struct cred *cred = current_cred();
+
+ return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
}
static int selinux_syslog(int type)
/* Derived from fs/exec.c:flush_old_files. */
static inline void flush_unauthorized_files(struct files_struct *files)
{
+ const struct cred *cred = current_cred();
struct avc_audit_data ad;
struct file *file, *devnull = NULL;
struct tty_struct *tty;
interested in the inode-based check here. */
file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list);
inode = file->f_path.dentry->d_inode;
- if (inode_has_perm(current, inode,
+ if (inode_has_perm(cred, inode,
FILE__READ | FILE__WRITE, NULL)) {
drop_tty = 1;
}
file = fget(i);
if (!file)
continue;
- if (file_has_perm(current,
+ if (file_has_perm(cred,
file,
file_to_av(file))) {
sys_close(i);
static int selinux_sb_kern_mount(struct super_block *sb, void *data)
{
+ const struct cred *cred = current_cred();
struct avc_audit_data ad;
int rc;
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = sb->s_root;
- return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
+ return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
}
static int selinux_sb_statfs(struct dentry *dentry)
{
+ const struct cred *cred = current_cred();
struct avc_audit_data ad;
AVC_AUDIT_DATA_INIT(&ad, FS);
ad.u.fs.path.dentry = dentry->d_sb->s_root;
- return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
+ return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
}
static int selinux_mount(char *dev_name,
unsigned long flags,
void *data)
{
+ const struct cred *cred = current_cred();
int rc;
rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
return rc;
if (flags & MS_REMOUNT)
- return superblock_has_perm(current, path->mnt->mnt_sb,
+ return superblock_has_perm(cred, path->mnt->mnt_sb,
FILESYSTEM__REMOUNT, NULL);
else
- return dentry_has_perm(current, path->mnt, path->dentry,
+ return dentry_has_perm(cred, path->mnt, path->dentry,
FILE__MOUNTON);
}
static int selinux_umount(struct vfsmount *mnt, int flags)
{
+ const struct cred *cred = current_cred();
int rc;
rc = secondary_ops->sb_umount(mnt, flags);
if (rc)
return rc;
- return superblock_has_perm(current, mnt->mnt_sb,
+ return superblock_has_perm(cred, mnt->mnt_sb,
FILESYSTEM__UNMOUNT, NULL);
}
static int selinux_inode_readlink(struct dentry *dentry)
{
- return dentry_has_perm(current, NULL, dentry, FILE__READ);
+ const struct cred *cred = current_cred();
+
+ return dentry_has_perm(cred, NULL, dentry, FILE__READ);
}
static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
{
+ const struct cred *cred = current_cred();
int rc;
rc = secondary_ops->inode_follow_link(dentry, nameidata);
if (rc)
return rc;
- return dentry_has_perm(current, NULL, dentry, FILE__READ);
+ return dentry_has_perm(cred, NULL, dentry, FILE__READ);
}
static int selinux_inode_permission(struct inode *inode, int mask)
{
+ const struct cred *cred = current_cred();
int rc;
rc = secondary_ops->inode_permission(inode, mask);
return 0;
}
- return inode_has_perm(current, inode,
+ return inode_has_perm(cred, inode,
file_mask_to_av(inode->i_mode, mask), NULL);
}
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
{
+ const struct cred *cred = current_cred();
int rc;
rc = secondary_ops->inode_setattr(dentry, iattr);
if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
ATTR_ATIME_SET | ATTR_MTIME_SET))
- return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+ return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
- return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
+ return dentry_has_perm(cred, NULL, dentry, FILE__WRITE);
}
static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
{
- return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
+ const struct cred *cred = current_cred();
+
+ return dentry_has_perm(cred, mnt, dentry, FILE__GETATTR);
}
static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
{
+ const struct cred *cred = current_cred();
+
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
if (!strcmp(name, XATTR_NAME_CAPS)) {
/* Not an attribute we recognize, so just check the
ordinary setattr permission. */
- return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+ return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
}
static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
{
- return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+ const struct cred *cred = current_cred();
+
+ return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
}
static int selinux_inode_listxattr(struct dentry *dentry)
{
- return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+ const struct cred *cred = current_cred();
+
+ return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
}
static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
static int selinux_revalidate_file_permission(struct file *file, int mask)
{
+ const struct cred *cred = current_cred();
int rc;
struct inode *inode = file->f_path.dentry->d_inode;
if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
mask |= MAY_APPEND;
- rc = file_has_perm(current, file,
+ rc = file_has_perm(cred, file,
file_mask_to_av(inode->i_mode, mask));
if (rc)
return rc;
static int selinux_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ const struct cred *cred = current_cred();
u32 av = 0;
if (_IOC_DIR(cmd) & _IOC_WRITE)
if (!av)
av = FILE__IOCTL;
- return file_has_perm(current, file, av);
+ return file_has_perm(cred, file, av);
}
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
{
+ const struct cred *cred = current_cred();
+
#ifndef CONFIG_PPC32
if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
/*
if (prot & PROT_EXEC)
av |= FILE__EXECUTE;
- return file_has_perm(current, file, av);
+ return file_has_perm(cred, file, av);
}
return 0;
}
unsigned long reqprot,
unsigned long prot)
{
+ const struct cred *cred = current_cred();
int rc;
rc = secondary_ops->file_mprotect(vma, reqprot, prot);
* modified content. This typically should only
* occur for text relocations.
*/
- rc = file_has_perm(current, vma->vm_file,
+ rc = file_has_perm(cred, vma->vm_file,
FILE__EXECMOD);
}
if (rc)
static int selinux_file_lock(struct file *file, unsigned int cmd)
{
- return file_has_perm(current, file, FILE__LOCK);
+ const struct cred *cred = current_cred();
+
+ return file_has_perm(cred, file, FILE__LOCK);
}
static int selinux_file_fcntl(struct file *file, unsigned int cmd,
unsigned long arg)
{
+ const struct cred *cred = current_cred();
int err = 0;
switch (cmd) {
}
if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
- err = file_has_perm(current, file, FILE__WRITE);
+ err = file_has_perm(cred, file, FILE__WRITE);
break;
}
/* fall through */
case F_GETOWN:
case F_GETSIG:
/* Just check FD__USE permission */
- err = file_has_perm(current, file, 0);
+ err = file_has_perm(cred, file, 0);
break;
case F_GETLK:
case F_SETLK:
err = -EINVAL;
break;
}
- err = file_has_perm(current, file, FILE__LOCK);
+ err = file_has_perm(cred, file, FILE__LOCK);
break;
}
static int selinux_file_receive(struct file *file)
{
- return file_has_perm(current, file, file_to_av(file));
+ const struct cred *cred = current_cred();
+
+ return file_has_perm(cred, file, file_to_av(file));
}
static int selinux_dentry_open(struct file *file)
{
+ const struct cred *cred = current_cred();
struct file_security_struct *fsec;
struct inode *inode;
struct inode_security_struct *isec;
* new inode label or new policy.
* This check is not redundant - do not remove.
*/
- return inode_has_perm(current, inode, open_file_to_av(file), NULL);
+ return inode_has_perm(cred, inode, open_file_to_av(file), NULL);
}
/* task security operations */