return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
}
-static int inode_has_perm_noadp(const struct cred *cred,
- struct inode *inode,
- u32 perms,
- unsigned flags)
-{
- struct common_audit_data ad;
- struct selinux_audit_data sad = {0,};
-
- COMMON_AUDIT_DATA_INIT(&ad, INODE);
- ad.u.inode = inode;
- ad.selinux_audit_data = &sad;
- return inode_has_perm(cred, inode, perms, &ad, flags);
-}
-
/* 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. */
spin_lock(&tty_files_lock);
if (!list_empty(&tty->tty_files)) {
struct tty_file_private *file_priv;
- struct inode *inode;
/* Revalidate access to controlling tty.
- Use inode_has_perm on the tty inode directly rather
+ Use path_has_perm on the tty path directly rather
than using file_has_perm, as this particular open
file may belong to another process and we are only
interested in the inode-based check here. */
file_priv = list_first_entry(&tty->tty_files,
struct tty_file_private, list);
file = file_priv->file;
- inode = file->f_path.dentry->d_inode;
- if (inode_has_perm_noadp(cred, inode,
- FILE__READ | FILE__WRITE, 0)) {
+ if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
drop_tty = 1;
- }
}
spin_unlock(&tty_files_lock);
tty_kref_put(tty);
u32 perms;
bool from_access;
unsigned flags = mask & MAY_NOT_BLOCK;
+ struct inode_security_struct *isec;
+ u32 sid;
+ struct av_decision avd;
+ int rc, rc2;
+ u32 audited, denied;
from_access = mask & MAY_ACCESS;
mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
if (!mask)
return 0;
+ validate_creds(cred);
+
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+ perms = file_mask_to_av(inode->i_mode, mask);
+
+ sid = cred_sid(cred);
+ isec = inode->i_security;
+
+ rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
+ audited = avc_audit_required(perms, &avd, rc,
+ from_access ? FILE__AUDIT_ACCESS : 0,
+ &denied);
+ if (likely(!audited))
+ return rc;
+
COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.selinux_audit_data = &sad;
ad.u.inode = inode;
if (from_access)
ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
- perms = file_mask_to_av(inode->i_mode, mask);
-
- return inode_has_perm(cred, inode, perms, &ad, flags);
+ rc2 = slow_avc_audit(sid, isec->sid, isec->sclass, perms,
+ audited, denied, &ad, flags);
+ if (rc2)
+ return rc2;
+ return rc;
}
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
rc = security_context_to_sid(value, size, &newsid);
if (rc == -EINVAL) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!capable(CAP_MAC_ADMIN)) {
+ struct audit_buffer *ab;
+ size_t audit_size;
+ const char *str;
+
+ /* We strip a nul only if it is at the end, otherwise the
+ * context contains a nul and we should audit that */
+ str = value;
+ if (str[size - 1] == '\0')
+ audit_size = size - 1;
+ else
+ audit_size = size;
+ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ audit_log_format(ab, "op=setxattr invalid_context=");
+ audit_log_n_untrustedstring(ab, value, audit_size);
+ audit_log_end(ab);
+
return rc;
+ }
rc = security_context_to_sid_force(value, size, &newsid);
}
if (rc)
static int selinux_file_open(struct file *file, const struct cred *cred)
{
struct file_security_struct *fsec;
- struct inode *inode;
struct inode_security_struct *isec;
- inode = file->f_path.dentry->d_inode;
fsec = file->f_security;
- isec = inode->i_security;
+ isec = file->f_path.dentry->d_inode->i_security;
/*
* Save inode label and policy sequence number
* at open-time so that selinux_file_permission
* new inode label or new policy.
* This check is not redundant - do not remove.
*/
- return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
+ return path_has_perm(cred, &file->f_path, open_file_to_av(file));
}
/* task security operations */
}
error = security_context_to_sid(value, size, &sid);
if (error == -EINVAL && !strcmp(name, "fscreate")) {
- if (!capable(CAP_MAC_ADMIN))
+ if (!capable(CAP_MAC_ADMIN)) {
+ struct audit_buffer *ab;
+ size_t audit_size;
+
+ /* We strip a nul only if it is at the end, otherwise the
+ * context contains a nul and we should audit that */
+ if (str[size - 1] == '\0')
+ audit_size = size - 1;
+ else
+ audit_size = size;
+ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+ audit_log_format(ab, "op=fscreate invalid_context=");
+ audit_log_n_untrustedstring(ab, value, audit_size);
+ audit_log_end(ab);
+
return error;
+ }
error = security_context_to_sid_force(value, size,
&sid);
}