]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - security/security.c
Merge branch 'next-evm' of git://github.com/mzohar/linux-evm into next
[linux-2.6.git] / security / security.c
index 1b798d3df71057720d799f5d3e1382880fde8f78..c1d69875db6c0a9fcc1a11b90d4d6711d794ff12 100644 (file)
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/ima.h>
+#include <linux/evm.h>
+
+#define MAX_LSM_EVM_XATTR      2
 
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
        CONFIG_DEFAULT_SECURITY;
 
-/* things that live in capability.c */
-extern void __init security_fixup_ops(struct security_operations *ops);
-
 static struct security_operations *security_ops;
 static struct security_operations default_security_ops = {
        .name   = "default",
@@ -154,39 +155,37 @@ int security_capset(struct cred *new, const struct cred *old,
                                    effective, inheritable, permitted);
 }
 
-int security_capable(int cap)
+int security_capable(struct user_namespace *ns, const struct cred *cred,
+                    int cap)
 {
-       return security_ops->capable(current, current_cred(), cap,
+       return security_ops->capable(current, cred, ns, cap,
                                     SECURITY_CAP_AUDIT);
 }
 
-int security_real_capable(struct task_struct *tsk, int cap)
+int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
+                         int cap)
 {
        const struct cred *cred;
        int ret;
 
        cred = get_task_cred(tsk);
-       ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_AUDIT);
+       ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_AUDIT);
        put_cred(cred);
        return ret;
 }
 
-int security_real_capable_noaudit(struct task_struct *tsk, int cap)
+int security_real_capable_noaudit(struct task_struct *tsk,
+                                 struct user_namespace *ns, int cap)
 {
        const struct cred *cred;
        int ret;
 
        cred = get_task_cred(tsk);
-       ret = security_ops->capable(tsk, cred, cap, SECURITY_CAP_NOAUDIT);
+       ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_NOAUDIT);
        put_cred(cred);
        return ret;
 }
 
-int security_sysctl(struct ctl_table *table, int op)
-{
-       return security_ops->sysctl(table, op);
-}
-
 int security_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
        return security_ops->quotactl(cmds, type, id, sb);
@@ -202,7 +201,7 @@ int security_syslog(int type)
        return security_ops->syslog(type);
 }
 
-int security_settime(struct timespec *ts, struct timezone *tz)
+int security_settime(const struct timespec *ts, const struct timezone *tz)
 {
        return security_ops->settime(ts, tz);
 }
@@ -272,6 +271,11 @@ int security_sb_copy_data(char *orig, char *copy)
 }
 EXPORT_SYMBOL(security_sb_copy_data);
 
+int security_sb_remount(struct super_block *sb, void *data)
+{
+       return security_ops->sb_remount(sb, data);
+}
+
 int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
        return security_ops->sb_kern_mount(sb, flags, data);
@@ -331,19 +335,58 @@ int security_inode_alloc(struct inode *inode)
 
 void security_inode_free(struct inode *inode)
 {
-       ima_inode_free(inode);
+       integrity_inode_free(inode);
        security_ops->inode_free_security(inode);
 }
 
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                 char **name, void **value, size_t *len)
+                                const struct qstr *qstr,
+                                const initxattrs initxattrs, void *fs_data)
 {
+       struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
+       struct xattr *lsm_xattr, *evm_xattr, *xattr;
+       int ret;
+
        if (unlikely(IS_PRIVATE(inode)))
-               return -EOPNOTSUPP;
-       return security_ops->inode_init_security(inode, dir, name, value, len);
+               return 0;
+
+       memset(new_xattrs, 0, sizeof new_xattrs);
+       if (!initxattrs)
+               return security_ops->inode_init_security(inode, dir, qstr,
+                                                        NULL, NULL, NULL);
+       lsm_xattr = new_xattrs;
+       ret = security_ops->inode_init_security(inode, dir, qstr,
+                                               &lsm_xattr->name,
+                                               &lsm_xattr->value,
+                                               &lsm_xattr->value_len);
+       if (ret)
+               goto out;
+
+       evm_xattr = lsm_xattr + 1;
+       ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
+       if (ret)
+               goto out;
+       ret = initxattrs(inode, new_xattrs, fs_data);
+out:
+       for (xattr = new_xattrs; xattr->name != NULL; xattr++) {
+               kfree(xattr->name);
+               kfree(xattr->value);
+       }
+       return (ret == -EOPNOTSUPP) ? 0 : ret;
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
+int security_old_inode_init_security(struct inode *inode, struct inode *dir,
+                                    const struct qstr *qstr, char **name,
+                                    void **value, size_t *len)
+{
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+       return security_ops->inode_init_security(inode, dir, qstr, name, value,
+                                                len);
+}
+EXPORT_SYMBOL(security_old_inode_init_security);
+
 #ifdef CONFIG_SECURITY_PATH
 int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
                        unsigned int dev)
@@ -360,6 +403,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
                return 0;
        return security_ops->path_mkdir(dir, dentry, mode);
 }
+EXPORT_SYMBOL(security_path_mkdir);
 
 int security_path_rmdir(struct path *dir, struct dentry *dentry)
 {
@@ -374,6 +418,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
                return 0;
        return security_ops->path_unlink(dir, dentry);
 }
+EXPORT_SYMBOL(security_path_unlink);
 
 int security_path_symlink(struct path *dir, struct dentry *dentry,
                          const char *old_name)
@@ -400,6 +445,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
        return security_ops->path_rename(old_dir, old_dentry, new_dir,
                                         new_dentry);
 }
+EXPORT_SYMBOL(security_path_rename);
 
 int security_path_truncate(struct path *path)
 {
@@ -515,9 +561,14 @@ int security_inode_permission(struct inode *inode, int mask)
 
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
+       int ret;
+
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
-       return security_ops->inode_setattr(dentry, attr);
+       ret = security_ops->inode_setattr(dentry, attr);
+       if (ret)
+               return ret;
+       return evm_inode_setattr(dentry, attr);
 }
 EXPORT_SYMBOL_GPL(security_inode_setattr);
 
@@ -531,9 +582,14 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 int security_inode_setxattr(struct dentry *dentry, const char *name,
                            const void *value, size_t size, int flags)
 {
+       int ret;
+
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
-       return security_ops->inode_setxattr(dentry, name, value, size, flags);
+       ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
+       if (ret)
+               return ret;
+       return evm_inode_setxattr(dentry, name, value, size);
 }
 
 void security_inode_post_setxattr(struct dentry *dentry, const char *name,
@@ -542,6 +598,7 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return;
        security_ops->inode_post_setxattr(dentry, name, value, size, flags);
+       evm_inode_post_setxattr(dentry, name, value, size);
 }
 
 int security_inode_getxattr(struct dentry *dentry, const char *name)
@@ -560,9 +617,14 @@ int security_inode_listxattr(struct dentry *dentry)
 
 int security_inode_removexattr(struct dentry *dentry, const char *name)
 {
+       int ret;
+
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
-       return security_ops->inode_removexattr(dentry, name);
+       ret = security_ops->inode_removexattr(dentry, name);
+       if (ret)
+               return ret;
+       return evm_inode_removexattr(dentry, name);
 }
 
 int security_inode_need_killpriv(struct dentry *dentry)
@@ -977,8 +1039,7 @@ EXPORT_SYMBOL(security_inode_getsecctx);
 
 #ifdef CONFIG_SECURITY_NETWORK
 
-int security_unix_stream_connect(struct socket *sock, struct socket *other,
-                                struct sock *newsk)
+int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
 {
        return security_ops->unix_stream_connect(sock, other, newsk);
 }
@@ -1093,7 +1154,7 @@ void security_sk_clone(const struct sock *sk, struct sock *newsk)
 
 void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
 {
-       security_ops->sk_getsecid(sk, &fl->secid);
+       security_ops->sk_getsecid(sk, &fl->flowi_secid);
 }
 EXPORT_SYMBOL(security_sk_classify_flow);
 
@@ -1226,7 +1287,8 @@ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
 }
 
 int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
-                                      struct xfrm_policy *xp, struct flowi *fl)
+                                      struct xfrm_policy *xp,
+                                      const struct flowi *fl)
 {
        return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
 }
@@ -1238,7 +1300,7 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
 
 void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
 {
-       int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);
+       int rc = security_ops->xfrm_decode_session(skb, &fl->flowi_secid, 0);
 
        BUG_ON(rc);
 }