]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - security/security.c
userns: allow ptrace from non-init user namespaces
[linux-2.6.git] / security / security.c
index 7da630a8c065de26a42b907b0aa98bc2ece95fd7..101142369db45c0846ca3dbe064b90a2ea83fbf9 100644 (file)
@@ -23,12 +23,14 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
        CONFIG_DEFAULT_SECURITY;
 
 /* things that live in capability.c */
-extern struct security_operations default_security_ops;
-extern void security_fixup_ops(struct security_operations *ops);
+extern void __init security_fixup_ops(struct security_operations *ops);
 
-struct security_operations *security_ops;      /* Initialized to NULL */
+static struct security_operations *security_ops;
+static struct security_operations default_security_ops = {
+       .name   = "default",
+};
 
-static inline int verify(struct security_operations *ops)
+static inline int __init verify(struct security_operations *ops)
 {
        /* verify the security_operations structure exists */
        if (!ops)
@@ -63,6 +65,11 @@ int __init security_init(void)
        return 0;
 }
 
+void reset_security_ops(void)
+{
+       security_ops = &default_security_ops;
+}
+
 /* Save user chosen LSM */
 static int __init choose_lsm(char *str)
 {
@@ -82,20 +89,12 @@ __setup("security=", choose_lsm);
  * Return true if:
  *     -The passed LSM is the one chosen by user at boot time,
  *     -or the passed LSM is configured as the default and the user did not
- *      choose an alternate LSM at boot time,
- *     -or there is no default LSM set and the user didn't specify a
- *      specific LSM and we're the first to ask for registration permission,
- *     -or the passed LSM is currently loaded.
+ *      choose an alternate LSM at boot time.
  * Otherwise, return false.
  */
 int __init security_module_enable(struct security_operations *ops)
 {
-       if (!*chosen_lsm)
-               strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX);
-       else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX))
-               return 0;
-
-       return 1;
+       return !strcmp(ops->name, chosen_lsm);
 }
 
 /**
@@ -155,44 +154,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_acct(struct file *file)
-{
-       return security_ops->acct(file);
-}
-
-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);
@@ -208,7 +200,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);
 }
@@ -278,6 +270,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);
@@ -299,46 +296,16 @@ int security_sb_mount(char *dev_name, struct path *path,
        return security_ops->sb_mount(dev_name, path, type, flags, data);
 }
 
-int security_sb_check_sb(struct vfsmount *mnt, struct path *path)
-{
-       return security_ops->sb_check_sb(mnt, path);
-}
-
 int security_sb_umount(struct vfsmount *mnt, int flags)
 {
        return security_ops->sb_umount(mnt, flags);
 }
 
-void security_sb_umount_close(struct vfsmount *mnt)
-{
-       security_ops->sb_umount_close(mnt);
-}
-
-void security_sb_umount_busy(struct vfsmount *mnt)
-{
-       security_ops->sb_umount_busy(mnt);
-}
-
-void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data)
-{
-       security_ops->sb_post_remount(mnt, flags, data);
-}
-
-void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint)
-{
-       security_ops->sb_post_addmount(mnt, mountpoint);
-}
-
 int security_sb_pivotroot(struct path *old_path, struct path *new_path)
 {
        return security_ops->sb_pivotroot(old_path, new_path);
 }
 
-void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
-{
-       security_ops->sb_post_pivotroot(old_path, new_path);
-}
-
 int security_sb_set_mnt_opts(struct super_block *sb,
                                struct security_mnt_opts *opts)
 {
@@ -361,16 +328,8 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);
 
 int security_inode_alloc(struct inode *inode)
 {
-       int ret;
-
        inode->i_security = NULL;
-       ret =  security_ops->inode_alloc_security(inode);
-       if (ret)
-               return ret;
-       ret = ima_inode_alloc(inode);
-       if (ret)
-               security_inode_free(inode);
-       return ret;
+       return security_ops->inode_alloc_security(inode);
 }
 
 void security_inode_free(struct inode *inode)
@@ -380,51 +339,55 @@ void security_inode_free(struct inode *inode)
 }
 
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                 char **name, void **value, size_t *len)
+                                const struct qstr *qstr, char **name,
+                                void **value, size_t *len)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return -EOPNOTSUPP;
-       return security_ops->inode_init_security(inode, dir, name, value, len);
+       return security_ops->inode_init_security(inode, dir, qstr, name, value,
+                                                len);
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
 #ifdef CONFIG_SECURITY_PATH
-int security_path_mknod(struct path *path, struct dentry *dentry, int mode,
+int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
                        unsigned int dev)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
                return 0;
-       return security_ops->path_mknod(path, dentry, mode, dev);
+       return security_ops->path_mknod(dir, dentry, mode, dev);
 }
 EXPORT_SYMBOL(security_path_mknod);
 
-int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
+int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
                return 0;
-       return security_ops->path_mkdir(path, dentry, mode);
+       return security_ops->path_mkdir(dir, dentry, mode);
 }
+EXPORT_SYMBOL(security_path_mkdir);
 
-int security_path_rmdir(struct path *path, struct dentry *dentry)
+int security_path_rmdir(struct path *dir, struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
                return 0;
-       return security_ops->path_rmdir(path, dentry);
+       return security_ops->path_rmdir(dir, dentry);
 }
 
-int security_path_unlink(struct path *path, struct dentry *dentry)
+int security_path_unlink(struct path *dir, struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
                return 0;
-       return security_ops->path_unlink(path, dentry);
+       return security_ops->path_unlink(dir, dentry);
 }
+EXPORT_SYMBOL(security_path_unlink);
 
-int security_path_symlink(struct path *path, struct dentry *dentry,
+int security_path_symlink(struct path *dir, struct dentry *dentry,
                          const char *old_name)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
                return 0;
-       return security_ops->path_symlink(path, dentry, old_name);
+       return security_ops->path_symlink(dir, dentry, old_name);
 }
 
 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -444,13 +407,13 @@ 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, loff_t length,
-                          unsigned int time_attrs)
+int security_path_truncate(struct path *path)
 {
        if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
                return 0;
-       return security_ops->path_truncate(path, length, time_attrs);
+       return security_ops->path_truncate(path);
 }
 
 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
@@ -558,6 +521,15 @@ int security_inode_permission(struct inode *inode, int mask)
        return security_ops->inode_permission(inode, mask);
 }
 
+int security_inode_exec_permission(struct inode *inode, unsigned int flags)
+{
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+       if (flags)
+               return -ECHILD;
+       return security_ops->inode_permission(inode, MAY_EXEC);
+}
+
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
@@ -573,13 +545,6 @@ int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
        return security_ops->inode_getattr(mnt, dentry);
 }
 
-void security_inode_delete(struct inode *inode)
-{
-       if (unlikely(IS_PRIVATE(inode)))
-               return;
-       security_ops->inode_delete(inode);
-}
-
 int security_inode_setxattr(struct dentry *dentry, const char *name,
                            const void *value, size_t size, int flags)
 {
@@ -630,14 +595,14 @@ int security_inode_killpriv(struct dentry *dentry)
 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
 {
        if (unlikely(IS_PRIVATE(inode)))
-               return 0;
+               return -EOPNOTSUPP;
        return security_ops->inode_getsecurity(inode, name, buffer, alloc);
 }
 
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
 {
        if (unlikely(IS_PRIVATE(inode)))
-               return 0;
+               return -EOPNOTSUPP;
        return security_ops->inode_setsecurity(inode, name, value, size, flags);
 }
 
@@ -655,7 +620,13 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
 
 int security_file_permission(struct file *file, int mask)
 {
-       return security_ops->file_permission(file, mask);
+       int ret;
+
+       ret = security_ops->file_permission(file, mask);
+       if (ret)
+               return ret;
+
+       return fsnotify_perm(file, mask);
 }
 
 int security_file_alloc(struct file *file)
@@ -719,7 +690,13 @@ int security_file_receive(struct file *file)
 
 int security_dentry_open(struct file *file, const struct cred *cred)
 {
-       return security_ops->dentry_open(file, cred);
+       int ret;
+
+       ret = security_ops->dentry_open(file, cred);
+       if (ret)
+               return ret;
+
+       return fsnotify_perm(file, MAY_OPEN);
 }
 
 int security_task_create(unsigned long clone_flags)
@@ -742,11 +719,6 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
        return security_ops->cred_prepare(new, old, gfp);
 }
 
-void security_commit_creds(struct cred *new, const struct cred *old)
-{
-       security_ops->cred_commit(new, old);
-}
-
 void security_transfer_creds(struct cred *new, const struct cred *old)
 {
        security_ops->cred_transfer(new, old);
@@ -767,22 +739,12 @@ int security_kernel_module_request(char *kmod_name)
        return security_ops->kernel_module_request(kmod_name);
 }
 
-int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
-{
-       return security_ops->task_setuid(id0, id1, id2, flags);
-}
-
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags)
 {
        return security_ops->task_fix_setuid(new, old, flags);
 }
 
-int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
-{
-       return security_ops->task_setgid(id0, id1, id2, flags);
-}
-
 int security_task_setpgid(struct task_struct *p, pid_t pgid)
 {
        return security_ops->task_setpgid(p, pgid);
@@ -804,11 +766,6 @@ void security_task_getsecid(struct task_struct *p, u32 *secid)
 }
 EXPORT_SYMBOL(security_task_getsecid);
 
-int security_task_setgroups(struct group_info *group_info)
-{
-       return security_ops->task_setgroups(group_info);
-}
-
 int security_task_setnice(struct task_struct *p, int nice)
 {
        return security_ops->task_setnice(p, nice);
@@ -824,15 +781,15 @@ int security_task_getioprio(struct task_struct *p)
        return security_ops->task_getioprio(p);
 }
 
-int security_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
+int security_task_setrlimit(struct task_struct *p, unsigned int resource,
+               struct rlimit *new_rlim)
 {
-       return security_ops->task_setrlimit(resource, new_rlim);
+       return security_ops->task_setrlimit(p, resource, new_rlim);
 }
 
-int security_task_setscheduler(struct task_struct *p,
-                               int policy, struct sched_param *lp)
+int security_task_setscheduler(struct task_struct *p)
 {
-       return security_ops->task_setscheduler(p, policy, lp);
+       return security_ops->task_setscheduler(p);
 }
 
 int security_task_getscheduler(struct task_struct *p)
@@ -1037,8 +994,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);
 }
@@ -1153,7 +1109,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);
 
@@ -1188,6 +1144,24 @@ void security_inet_conn_established(struct sock *sk,
        security_ops->inet_conn_established(sk, skb);
 }
 
+int security_secmark_relabel_packet(u32 secid)
+{
+       return security_ops->secmark_relabel_packet(secid);
+}
+EXPORT_SYMBOL(security_secmark_relabel_packet);
+
+void security_secmark_refcount_inc(void)
+{
+       security_ops->secmark_refcount_inc();
+}
+EXPORT_SYMBOL(security_secmark_refcount_inc);
+
+void security_secmark_refcount_dec(void)
+{
+       security_ops->secmark_refcount_dec();
+}
+EXPORT_SYMBOL(security_secmark_refcount_dec);
+
 int security_tun_dev_create(void)
 {
        return security_ops->tun_dev_create();
@@ -1268,7 +1242,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);
 }
@@ -1280,7 +1255,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);
 }
@@ -1312,13 +1287,6 @@ int security_key_getsecurity(struct key *key, char **_buffer)
        return security_ops->key_getsecurity(key, _buffer);
 }
 
-int security_key_session_to_parent(const struct cred *cred,
-                                  const struct cred *parent_cred,
-                                  struct key *key)
-{
-       return security_ops->key_session_to_parent(cred, parent_cred, key);
-}
-
 #endif /* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT