summaryrefslogtreecommitdiff
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c43
1 files changed, 41 insertions, 2 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 623108199641..8890dce9cf71 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3228,6 +3228,44 @@ static void selinux_file_free_security(struct file *file)
file_free_security(file);
}
+/*
+ * Check whether a task has the ioctl permission and cmd
+ * operation to an inode.
+ */
+int ioctl_has_perm(const struct cred *cred, struct file *file,
+ u32 requested, u16 cmd)
+{
+ struct common_audit_data ad;
+ struct file_security_struct *fsec = file->f_security;
+ struct inode *inode = file_inode(file);
+ struct inode_security_struct *isec = inode->i_security;
+ struct lsm_ioctlop_audit ioctl;
+ u32 ssid = cred_sid(cred);
+ int rc;
+
+ ad.type = LSM_AUDIT_DATA_IOCTL_OP;
+ ad.u.op = &ioctl;
+ ad.u.op->cmd = cmd;
+ ad.u.op->path = file->f_path;
+
+ if (ssid != fsec->sid) {
+ rc = avc_has_perm(ssid, fsec->sid,
+ SECCLASS_FD,
+ FD__USE,
+ &ad);
+ if (rc)
+ goto out;
+ }
+
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+ rc = avc_has_operation(ssid, isec->sid, isec->sclass,
+ requested, cmd, &ad);
+out:
+ return rc;
+}
+
static int selinux_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -3270,7 +3308,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
* to the file's ioctl() function.
*/
default:
- error = file_has_perm(cred, file, FILE__IOCTL);
+ error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
}
return error;
}
@@ -3283,7 +3321,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
int rc = 0;
if (default_noexec &&
- (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
+ (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
+ (!shared && (prot & PROT_WRITE)))) {
/*
* We are making executable an anonymous mapping or a
* private file mapping that will also be writable.