![[LWN Logo]](/images/lcorner.png) |
|
![[LWN.net]](/images/Included.png) |
From: Nick Bellinger <nickb@attheoffice.org>
To: linux-security-module@wirex.com
Subject: OpenWall SECURE_LINK as a LSM
Date: 09 Nov 2001 16:32:53 -0700
Greetings,
After a few months of lurking on the LSM mailing list, here is an
attempt at something constructive. Attached is Solar Designer's Openwall
SECURE_LINK feature as an LSM. Thanks to everybody who is working on
LSM, everybody in #kernelnewbies, and Emily Ratliff's NPROC_RLIMIT which
is an _excellent_ starting point for anyone who wants to get involved
with LSM.
Nick Bellinger
diff -urN linux-2.4.14-lsm-cvs/Documentation/Configure.help linux-2.4.14-lsm/Documentation/Configure.help
--- linux-2.4.14-lsm-cvs/Documentation/Configure.help Fri Nov 9 19:14:44 2001
+++ linux-2.4.14-lsm/Documentation/Configure.help Fri Nov 9 19:06:03 2001
@@ -19209,6 +19209,22 @@
If you are unsure how to answer this question, answer N.
+Restricted links in /tmp
+CONFIG_SECURITY_LINK
+ There's a very common attack that involves a malicious user creating
+ a symbolic link in /tmp, with a carefully chosen name, pointing at
+ another user's file. When the victim then writes to that file name,
+ without the required precautions, they inadvertently write to the
+ wrong file. Enabling this option reduces the impact of this class of
+ holes (some get fixed, many others allow for DoS attacks only, most
+ of the rest become harder to exploit) by preventing a process from
+ following a link which is in a +t directory, unless the link owner
+ is trusted (that is, it's the user we're running as or the directory
+ owner). To prevent from using a hard link in an attack instead, this
+ option does not allow users to create hard links to files they don't
+ own, unless they could read and write the file. This might break
+ things. Say Y if security is more important.
+
Domain and Type Enforcement
CONFIG_SECURITY_DTE
This enables Domain and Type Enforcement. It assigns labels to
diff -urN linux-2.4.14-lsm-cvs/security/Config.in linux-2.4.14-lsm/security/Config.in
--- linux-2.4.14-lsm-cvs/security/Config.in Fri Nov 9 19:14:19 2001
+++ linux-2.4.14-lsm/security/Config.in Fri Nov 9 19:05:27 2001
@@ -6,5 +6,6 @@
tristate 'Capabilities Support' CONFIG_SECURITY_CAPABILITIES
dep_tristate 'IP Networking Support' CONFIG_SECURITY_IP $CONFIG_NETFILTER
dep_tristate 'Add RLIMITS_NPROC check to execve (EXPERIMENTAL)' CONFIG_SECURITY_NPROC $CONFIG_EXPERIMENTAL
+dep_tristate 'Restricted links in /tmp (EXPERIMENTAL)' CONFIG_SECURITY_LINK $CONFIG_EXPERIMENTAL
dep_tristate 'Domain and Type Enforcement (EXPERIMENTAL)' CONFIG_SECURITY_DTE $CONFIG_EXPERIMENTAL
endmenu
diff -urN linux-2.4.14-lsm-cvs/security/Makefile linux-2.4.14-lsm/security/Makefile
--- linux-2.4.14-lsm-cvs/security/Makefile Fri Nov 9 19:14:13 2001
+++ linux-2.4.14-lsm/security/Makefile Fri Nov 9 19:07:41 2001
@@ -17,5 +17,6 @@
obj-$(CONFIG_SECURITY_CAPABILITIES) += capability.o
obj-$(CONFIG_SECURITY_IP) += lsm_ip_glue.o
obj-$(CONFIG_SECURITY_NPROC) += nproc.o
+obj-$(CONFIG_SECURITY_LINK) += slink.o
include $(TOPDIR)/Rules.make
diff -urN linux-2.4.14-lsm-cvs/security/slink.c linux-2.4.14-lsm/security/slink.c
--- linux-2.4.14-lsm-cvs/security/slink.c Wed Dec 31 16:00:00 1969
+++ linux-2.4.14-lsm/security/slink.c Fri Nov 9 19:00:51 2001
@@ -0,0 +1,1192 @@
+/*
+ * SECURE_LINK Linux Security Module
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This module is basically a LSM port of the SECURE_LINK
+ * part of Solar Designer's OpenWall 2.2 code and is based off
+ * of capability.c, dummy.c and Emily Ratliff's NPROC_RLIMIT module.
+ *
+ * LSM port by Nick Bellinger, Esquire <nickb@attheoffice.org>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/security.h>
+#include <linux/stat.h>
+#include <linux/netfilter.h>
+#include <linux/netlink.h>
+
+
+/* flag to keep track of how we were registered */
+static int secondary;
+
+static int slink_sethostname (char *hostname)
+{
+ return 0;
+}
+
+static int slink_setdomainname (char *domainname)
+{
+ return 0;
+}
+
+static int slink_reboot (unsigned int cmd)
+{
+ return 0;
+}
+
+static int slink_ioperm (unsigned long from, unsigned long num, int turn_on)
+{
+ return 0;
+}
+
+static int slink_iopl (unsigned int old, unsigned int level)
+{
+ return 0;
+}
+
+static int slink_ptrace (struct task_struct *parent, struct task_struct *child)
+{
+ return 0;
+}
+
+static int slink_capget (struct task_struct *target, kernel_cap_t * effective,
+ kernel_cap_t * inheritable, kernel_cap_t * permitted)
+{
+ return 0;
+}
+
+static int slink_capset_check (struct task_struct *target,
+ kernel_cap_t * effective,
+ kernel_cap_t * inheritable,
+ kernel_cap_t * permitted)
+{
+ return 0;
+}
+
+static void slink_capset_set (struct task_struct *target,
+ kernel_cap_t * effective,
+ kernel_cap_t * inheritable,
+ kernel_cap_t * permitted)
+{
+ return;
+}
+
+static int slink_acct (struct file *file)
+{
+ return 0;
+}
+
+static int slink_capable (struct task_struct *tsk, int cap)
+{
+ /* from dummy.c */
+ if (cap_is_fs_cap (cap) ? tsk->fsuid == 0 : tsk->euid == 0)
+ /* capability granted */
+ return 0;
+
+ /* capability denied */
+ return -EPERM;
+}
+
+static int slink_sysctl (ctl_table * table, int op)
+{
+ return 0;
+}
+
+static int slink_sys_security (unsigned int id, unsigned int call,
+ unsigned long *args)
+{
+ return -ENOSYS;
+}
+
+static int slink_swapon (struct dentry *dentry)
+{
+ return 0;
+}
+
+static int slink_swapoff (struct dentry *dentry)
+{
+ return 0;
+}
+
+static int slink_nfsservctl (int cmd, struct nfsctl_arg *arg)
+{
+ return 0;
+}
+
+static int slink_quotactl (int cmds, int type, int id, struct super_block *sb)
+{
+ return 0;
+}
+
+static int slink_quota_on (struct file *f)
+{
+ return 0;
+}
+
+static int slink_bdflush (int func, long data)
+{
+ return 0;
+}
+
+static int slink_syslog (int type)
+{
+ return 0;
+}
+
+static int slink_netlink_send (struct sk_buff *skb)
+{
+ /* from dummy.c */
+ if (current->euid == 0)
+ cap_raise (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN);
+ else
+ NETLINK_CB (skb).eff_cap = 0;
+ return 0;
+}
+
+static int slink_netlink_recv (struct sk_buff *skb)
+{
+ /* from dummy.c */
+ if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN))
+ return -EPERM;
+ return 0;
+}
+
+static int slink_binprm_alloc_security(struct linux_binprm *bprm)
+{
+ return 0;
+}
+
+static void slink_binprm_free_security (struct linux_binprm *bprm)
+{
+ return;
+}
+
+static void slink_binprm_compute_creds (struct linux_binprm *bprm)
+{
+ return;
+}
+
+static int slink_binprm_set_security (struct linux_binprm *bprm)
+{
+ return 0;
+}
+
+static int slink_sb_alloc_security (struct super_block *sb)
+{
+ return 0;
+}
+
+static void slink_sb_free_security (struct super_block *sb)
+{
+ return;
+}
+
+static int slink_sb_statfs (struct super_block *sb)
+{
+ return 0;
+}
+
+static int slink_sb_mount (char *devname, struct nameidata *nd, char *type,
+ unsigned long flags, void *data)
+{
+ return 0;
+}
+
+static int slink_sb_check_sb (struct vfsmount *mnt, struct nameidata *nd)
+{
+ return 0;
+}
+
+static int slink_sb_umount (struct vfsmount *mnt, int flags)
+{
+ return 0;
+}
+
+static void slink_sb_umount_close (struct vfsmount *mnt)
+{
+ return;
+}
+
+static void slink_sb_umount_busy (struct vfsmount *mnt)
+{
+ return;
+}
+static void slink_sb_post_remount (struct vfsmount *mnt, unsigned long flags,
+ void *data)
+{
+ return;
+}
+
+static void slink_sb_post_mountroot (struct super_block *sb)
+{
+ return;
+}
+
+static void slink_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
+{
+ return;
+}
+
+static int slink_inode_alloc_security (struct inode *inode)
+{
+ return 0;
+}
+
+static void slink_inode_free_security (struct inode *inode)
+{
+ return;
+}
+
+static int slink_inode_create (struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ return 0;
+}
+
+static void slink_inode_post_create (struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ return;
+}
+
+static int slink_inode_link (struct dentry *old_dentry, struct inode *inode,
+ struct dentry *new_dentry)
+{
+ int error;
+
+ if(current->fsuid != old_dentry->d_inode->i_uid &&
+ (!S_ISREG(old_dentry->d_inode->i_mode) || (old_dentry->d_inode->i_mode & S_ISUID) ||
+ ((old_dentry->d_inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
+ (error = permission(old_dentry->d_inode, MAY_READ | MAY_WRITE))) &&
+ !capable(CAP_FOWNER) && current->uid) {
+ printk(KERN_INFO "LSM/OpenWall: denied hardlink to %d.%d for %d.%d, pid %d\n",
+ old_dentry->d_inode->i_uid, old_dentry->d_inode->i_gid,
+ current->uid, current->euid, current->pid);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static void slink_inode_post_link (struct dentry *old_dentry,
+ struct inode *inode,
+ struct dentry *new_dentry)
+{
+ return;
+}
+
+static int slink_inode_unlink (struct inode *inode, struct dentry *dentry)
+{
+ return 0;
+}
+
+static int slink_inode_symlink (struct inode *inode, struct dentry *dentry,
+ const char *name)
+{
+ return 0;
+}
+
+static void slink_inode_post_symlink (struct inode *inode,
+ struct dentry *dentry, const char *name)
+{
+ return;
+}
+
+static int slink_inode_mkdir (struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ return 0;
+}
+
+static void slink_inode_post_mkdir (struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ return;
+}
+
+static int slink_inode_rmdir (struct inode *inode, struct dentry *dentry)
+{
+ return 0;
+}
+
+static int slink_inode_mknod (struct inode *inode, struct dentry *dentry,
+ int major, dev_t minor)
+{
+ return 0;
+}
+
+static void slink_inode_post_mknod (struct inode *inode, struct dentry *dentry,
+ int major, dev_t minor)
+{
+ return;
+}
+
+static int slink_inode_rename (struct inode *old_inode,
+ struct dentry *old_dentry,
+ struct inode *new_inode,
+ struct dentry *new_dentry)
+{
+ return 0;
+}
+
+static void slink_inode_post_rename (struct inode *old_inode,
+ struct dentry *old_dentry,
+ struct inode *new_inode,
+ struct dentry *new_dentry)
+{
+ return;
+}
+
+static int slink_inode_readlink (struct dentry *dentry)
+{
+ return 0;
+}
+
+static int slink_inode_follow_link (struct dentry *dentry,
+ struct nameidata *nameidata)
+{
+
+ if (S_ISLNK(dentry->d_inode->i_mode) && (dentry->d_parent->d_inode->i_mode & S_ISVTX) &&
+ dentry->d_parent->d_inode->i_uid != dentry->d_inode->i_uid &&
+ (dentry->d_parent->d_inode->i_mode & S_IWOTH) &&
+ current->fsuid != dentry->d_inode->i_uid) {
+ printk(KERN_INFO "LSM/OpenWall: not following symlink of %d.%d by %d.%d pid %d\n",
+ dentry->d_inode->i_uid, dentry->d_inode->i_gid,
+ current->uid, current->euid, current->pid);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+static int slink_inode_permission (struct inode *inode, int mask)
+{
+ return 0;
+}
+
+static int slink_inode_revalidate (struct dentry *inode)
+{
+ return 0;
+}
+
+static int slink_inode_setattr (struct dentry *dentry, struct iattr *iattr)
+{
+ return 0;
+}
+
+static int slink_inode_stat (struct inode *inode)
+{
+ return 0;
+}
+
+static void slink_post_lookup (struct inode *ino, struct dentry *d)
+{
+ return;
+}
+
+static void slink_delete (struct inode *ino)
+{
+ return;
+}
+
+static int slink_file_permission (struct file *file, int mask)
+{
+ return 0;
+}
+
+static int slink_file_alloc_security (struct file *file)
+{
+ return 0;
+}
+
+static void slink_file_free_security (struct file *file)
+{
+ return;
+}
+
+static int slink_file_llseek (struct file *file)
+{
+ return 0;
+}
+
+static int slink_file_ioctl (struct file *file, unsigned int command ,
+ unsigned long arg)
+{
+ return 0;
+}
+
+static int slink_file_mmap (struct file *file, unsigned long prot,
+ unsigned long flags)
+{
+ return 0;
+}
+
+static int slink_file_mprotect (struct vm_area_struct *vma, unsigned long prot)
+{
+ return 0;
+}
+
+static int slink_file_lock (struct file *file, unsigned int cmd)
+{
+ return 0;
+}
+
+static int slink_file_fcntl (struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+
+static int slink_file_set_fowner (struct file *file)
+{
+ return 0;
+}
+
+static int slink_file_send_sigiotask (struct task_struct *tsk,
+ struct fown_struct *fown,
+ int fd, int reason)
+{
+ return 0;
+}
+
+static int slink_file_receive (struct file *file)
+{
+ return 0;
+}
+
+static int slink_task_create (unsigned long clone_flags)
+{
+ return 0;
+}
+
+static int slink_task_alloc_security (struct task_struct *p)
+{
+ return 0;
+}
+
+static void slink_task_free_security (struct task_struct *p)
+{
+ return;
+}
+
+static int slink_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+ return 0;
+}
+
+static int slink_task_post_setuid(uid_t old_ruid, uid_t old_euid,
+ uid_t old_suid, int flags)
+{
+ return 0;
+}
+
+static int slink_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags)
+{
+ return 0;
+}
+
+static int slink_task_setpgid (struct task_struct *p, pid_t pgid)
+{
+ return 0;
+}
+
+static int slink_task_getpgid (struct task_struct *p)
+{
+ return 0;
+}
+
+static int slink_task_getsid (struct task_struct *p)
+{
+ return 0;
+}
+
+static int slink_task_setgroups (int gidsetsize, gid_t *grouplist)
+{
+ return 0;
+}
+
+static int slink_task_setnice (struct task_struct *p, int nice)
+{
+ return 0;
+}
+
+static int slink_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
+{
+ return 0;
+}
+
+static int slink_task_setscheduler (struct task_struct *p, int policy,
+ struct sched_param *lp)
+{
+ return 0;
+}
+
+static int slink_task_getscheduler (struct task_struct *p)
+{
+ return 0;
+}
+
+static int slink_task_wait (struct task_struct *p)
+{
+ return 0;
+}
+
+static int slink_task_kill (struct task_struct *p, struct siginfo *info, int sig)
+{
+ return 0;
+}
+
+static int slink_task_prctl (int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5)
+{
+ return 0;
+}
+
+static void slink_task_kmod_set_label (void)
+{
+ return;
+}
+
+static unsigned int slink_ip_preroute_first (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_preroute_last (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_input_first (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_input_last (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_forward_first (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_forward_last (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_output_first (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_output_last (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_postroute_first (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static unsigned int slink_ip_postroute_last (unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ return NF_ACCEPT;
+}
+
+static void slink_ip_fragment (struct sk_buff *newskb,
+ const struct sk_buff *oldskb)
+{
+ return;
+}
+
+static int slink_ip_defragment (struct sk_buff *skb)
+{
+ return 0;
+}
+
+static void slink_ip_encapsulate (struct sk_buff *skb)
+{
+ return;
+}
+
+static void slink_ip_decapsulate (struct sk_buff *skb)
+{
+ return;
+}
+
+static int slink_decode_options (struct sk_buff *skb, const char *optptr,
+ unsigned char **pp_ptr)
+{
+ /* from dummy.c */
+ if (!skb && !capable (CAP_NET_RAW)) {
+ (const unsigned char *) *pp_ptr = optptr;
+ return -EPERM;
+ }
+ return 0;
+}
+
+static void slink_netdev_unregister (struct net_device *dev)
+{
+ return;
+}
+
+static int slink_socket_create (int family, int type, int protocol)
+{
+ return 0;
+}
+static void slink_socket_post_create (struct socket *sock, int family,
+ int type, int protocol)
+{
+ return;
+}
+
+static int slink_socket_bind (struct socket *sock, struct sockaddr *address,
+ int addrlen)
+{
+ return 0;
+}
+
+static int slink_socket_connect (struct socket *sock, struct sockaddr *address,
+ int addrlen)
+{
+ return 0;
+}
+
+static int slink_socket_listen (struct socket *sock, int backlog)
+{
+ return 0;
+}
+
+static int slink_socket_accept (struct socket *sock, struct socket *newsock)
+{
+ return 0;
+}
+
+static int slink_socket_sendmsg (struct socket *sock, struct msghdr *msg,
+ int size)
+{
+ return 0;
+}
+
+static int slink_socket_recvmsg (struct socket *sock, struct msghdr *msg,
+ int size, int flags)
+{
+ return 0;
+}
+
+static int slink_socket_getsockname (struct socket *sock)
+{
+ return 0;
+}
+
+static int slink_socket_getpeername (struct socket *sock)
+{
+ return 0;
+}
+
+static int slink_socket_setsockopt (struct socket *sock, int level, int optname)
+{
+ return 0;
+}
+
+static int slink_socket_getsockopt (struct socket *sock, int level, int optname)
+{
+ return 0;
+}
+
+static int slink_socket_shutdown (struct socket *sock, int how)
+{
+ return 0;
+}
+
+static int slink_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
+{
+ return 0;
+}
+
+static int slink_socket_unix_stream_connect (struct socket *sock,
+ struct socket *other)
+{
+ return 0;
+}
+
+static int slink_socket_unix_may_send (struct socket *sock,
+ struct socket *other)
+{
+ return 0;
+}
+
+static int slink_module_create_module (const char *name_user, size_t size)
+{
+ return 0;
+}
+
+static int slink_module_init_module (struct module *mod)
+{
+ return 0;
+}
+
+static int slink_module_delete_module (const struct module *mod)
+{
+ return 0;
+}
+
+static int slink_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
+{
+ return 0;
+}
+
+static int slink_ipc_getinfo (int id, int cmd)
+{
+ return 0;
+}
+
+static int slink_msg_msg_alloc_security (struct msg_msg *msg)
+{
+ return 0;
+}
+
+static void slink_msg_msg_free_security (struct msg_msg *msg)
+{
+ return;
+}
+
+static int slink_msg_queue_alloc_security (struct msg_queue *msq)
+{
+ return 0;
+}
+
+static void slink_msg_queue_free_security (struct msg_queue *msq)
+{
+ return;
+}
+
+static int slink_msg_queue_associate (struct msg_queue *msq, int msgid,
+ int msgflg)
+{
+ return 0;
+}
+
+static int slink_msg_queue_msgctl (struct msg_queue *msq, int msgid, int cmd)
+{
+ return 0;
+}
+
+static int slink_msg_queue_msgsnd (struct msg_queue *msq, struct msg_msg *msg,
+ int msgid, int msgflg)
+{
+ return 0;
+}
+
+static int slink_msg_queue_msgrcv (struct msg_queue *msq, struct msg_msg *msg,
+ struct task_struct *target,
+ long type, int mode)
+{
+ return 0;
+}
+
+static int slink_shm_alloc_security (struct shmid_kernel *shp)
+{
+ return 0;
+}
+
+static void slink_shm_free_security (struct shmid_kernel *shp)
+{
+ return;
+}
+
+static int slink_shm_associate (struct shmid_kernel *shp, int shmid, int shmflg)
+{
+ return 0;
+}
+
+static int slink_shm_shmctl (struct shmid_kernel *shp, int shmid, int cmd)
+{
+ return 0;
+}
+
+static int slink_shm_shmat (struct shmid_kernel *shp, int shmid, char *shmaddr,
+ int shmflg)
+{
+ return 0;
+}
+
+static int slink_sem_alloc_security (struct sem_array *sma)
+{
+ return 0;
+}
+
+static void slink_sem_free_security (struct sem_array *sma)
+{
+ return;
+}
+
+static int slink_sem_associate (struct sem_array *sma, int semid, int semflg)
+{
+ return 0;
+}
+
+static int slink_sem_semctl (struct sem_array *sma, int semid, int cmd)
+{
+ return 0;
+}
+
+static int slink_sem_semop (struct sem_array *sma, int semid,
+ struct sembuf *sops, unsigned nsops, int alter)
+{
+ return 0;
+}
+
+static int slink_skb_alloc_security (struct sk_buff *skb)
+{
+ return 0;
+}
+
+static int slink_skb_clone (struct sk_buff *newskb,
+ const struct sk_buff *oldskb)
+{
+ return 0;
+}
+
+static void slink_skb_copy (struct sk_buff *newskb,
+ const struct sk_buff *oldskb)
+{
+ return;
+}
+
+static void slink_skb_set_owner_w (struct sk_buff *skb, struct sock *sk)
+{
+ return;
+}
+
+static void slink_skb_free_security (struct sk_buff *skb)
+{
+ return;
+}
+
+static int slink_register (const char *name, struct security_operations *ops)
+{
+ return -EINVAL;
+}
+
+static int slink_unregister (const char *name, struct security_operations *ops)
+{
+ return -EINVAL;
+}
+
+static struct binprm_security_ops slink_binprm_ops = {
+ alloc_security: slink_binprm_alloc_security,
+ free_security: slink_binprm_free_security,
+ compute_creds: slink_binprm_compute_creds,
+ set_security: slink_binprm_set_security,
+};
+
+static struct super_block_security_ops slink_sb_ops = {
+ alloc_security: slink_sb_alloc_security,
+ free_security: slink_sb_free_security,
+ statfs: slink_sb_statfs,
+ mount: slink_sb_mount,
+ check_sb: slink_sb_check_sb,
+ umount: slink_sb_umount,
+ umount_close: slink_sb_umount_close,
+ umount_busy: slink_sb_umount_busy,
+ post_remount: slink_sb_post_remount,
+ post_mountroot: slink_sb_post_mountroot,
+ post_addmount: slink_sb_post_addmount,
+};
+
+static struct inode_security_ops slink_inode_ops = {
+ alloc_security: slink_inode_alloc_security,
+ free_security: slink_inode_free_security,
+ create: slink_inode_create,
+ post_create: slink_inode_post_create,
+ link: slink_inode_link,
+ post_link: slink_inode_post_link,
+ unlink: slink_inode_unlink,
+ symlink: slink_inode_symlink,
+ post_symlink: slink_inode_post_symlink,
+ mkdir: slink_inode_mkdir,
+ post_mkdir: slink_inode_post_mkdir,
+ rmdir: slink_inode_rmdir,
+ mknod: slink_inode_mknod,
+ post_mknod: slink_inode_post_mknod,
+ rename: slink_inode_rename,
+ post_rename: slink_inode_post_rename,
+ readlink: slink_inode_readlink,
+ follow_link: slink_inode_follow_link,
+ permission: slink_inode_permission,
+ revalidate: slink_inode_revalidate,
+ setattr: slink_inode_setattr,
+ stat: slink_inode_stat,
+ post_lookup: slink_post_lookup,
+ delete: slink_delete,
+};
+
+static struct file_security_ops slink_file_ops = {
+ permission: slink_file_permission,
+ alloc_security: slink_file_alloc_security,
+ free_security: slink_file_free_security,
+ llseek: slink_file_llseek,
+ ioctl: slink_file_ioctl,
+ mmap: slink_file_mmap,
+ mprotect: slink_file_mprotect,
+ lock: slink_file_lock,
+ fcntl: slink_file_fcntl,
+ set_fowner: slink_file_set_fowner,
+ send_sigiotask: slink_file_send_sigiotask,
+ receive: slink_file_receive,
+};
+
+static struct task_security_ops slink_task_ops = {
+ create: slink_task_create,
+ alloc_security: slink_task_alloc_security,
+ free_security: slink_task_free_security,
+ setuid: slink_task_setuid,
+ post_setuid: slink_task_post_setuid,
+ setgid: slink_task_setgid,
+ setpgid: slink_task_setpgid,
+ getpgid: slink_task_getpgid,
+ getsid: slink_task_getsid,
+ setgroups: slink_task_setgroups,
+ setnice: slink_task_setnice,
+ setrlimit: slink_task_setrlimit,
+ setscheduler: slink_task_setscheduler,
+ getscheduler: slink_task_getscheduler,
+ wait: slink_task_wait,
+ kill: slink_task_kill,
+ prctl: slink_task_prctl,
+ kmod_set_label: slink_task_kmod_set_label,
+};
+
+static struct socket_security_ops slink_socket_ops = {
+ create: slink_socket_create,
+ post_create: slink_socket_post_create,
+ bind: slink_socket_bind,
+ connect: slink_socket_connect,
+ listen: slink_socket_listen,
+ accept: slink_socket_accept,
+ sendmsg: slink_socket_sendmsg,
+ recvmsg: slink_socket_recvmsg,
+ getsockname: slink_socket_getsockname,
+ getpeername: slink_socket_getpeername,
+ getsockopt: slink_socket_getsockopt,
+ setsockopt: slink_socket_setsockopt,
+ shutdown: slink_socket_shutdown,
+ sock_rcv_skb: slink_socket_sock_rcv_skb,
+ unix_stream_connect: slink_socket_unix_stream_connect,
+ unix_may_send: slink_socket_unix_may_send,
+};
+
+static struct skb_security_ops slink_skb_ops = {
+ alloc_security: slink_skb_alloc_security,
+ clone: slink_skb_clone,
+ copy: slink_skb_copy,
+ set_owner_w: slink_skb_set_owner_w,
+ free_security: slink_skb_free_security,
+};
+
+static struct ip_security_ops slink_ip_ops = {
+ preroute_first: slink_ip_preroute_first,
+ preroute_last: slink_ip_preroute_last,
+ input_first: slink_ip_input_first,
+ input_last: slink_ip_input_last,
+ forward_first: slink_ip_forward_first,
+ forward_last: slink_ip_forward_last,
+ output_first: slink_ip_output_first,
+ output_last: slink_ip_output_last,
+ postroute_first: slink_ip_postroute_first,
+ postroute_last: slink_ip_postroute_last,
+ fragment: slink_ip_fragment,
+ defragment: slink_ip_defragment,
+ encapsulate: slink_ip_encapsulate,
+ decapsulate: slink_ip_decapsulate,
+ decode_options: slink_decode_options,
+};
+
+static struct netdev_security_ops slink_netdev_ops = {
+ unregister: slink_netdev_unregister,
+};
+
+static struct module_security_ops slink_module_ops = {
+ create_module: slink_module_create_module,
+ init_module: slink_module_init_module,
+ delete_module: slink_module_delete_module,
+
+};
+
+static struct ipc_security_ops slink_ipc_ops = {
+ permission: slink_ipc_permission,
+ getinfo: slink_ipc_getinfo,
+};
+
+static struct msg_msg_security_ops slink_msg_ops = {
+ alloc_security: slink_msg_msg_alloc_security,
+ free_security: slink_msg_msg_free_security,
+};
+
+static struct msg_queue_security_ops slink_msg_queue_ops = {
+ alloc_security: slink_msg_queue_alloc_security,
+ free_security: slink_msg_queue_free_security,
+ associate: slink_msg_queue_associate,
+ msgctl: slink_msg_queue_msgctl,
+ msgsnd: slink_msg_queue_msgsnd,
+ msgrcv: slink_msg_queue_msgrcv,
+};
+
+static struct shm_security_ops slink_shm_ops = {
+ alloc_security: slink_shm_alloc_security,
+ free_security: slink_shm_free_security,
+ associate: slink_shm_associate,
+ shmctl: slink_shm_shmctl,
+ shmat: slink_shm_shmat,
+};
+
+static struct sem_security_ops slink_sem_ops = {
+ alloc_security: slink_sem_alloc_security,
+ free_security: slink_sem_free_security,
+ associate: slink_sem_associate,
+ semctl: slink_sem_semctl,
+ semop: slink_sem_semop,
+};
+
+static struct security_operations slink_ops = {
+ sethostname: slink_sethostname,
+ setdomainname: slink_setdomainname,
+ reboot: slink_reboot,
+ ioperm: slink_ioperm,
+ iopl: slink_iopl,
+ ptrace: slink_ptrace,
+ capget: slink_capget,
+ capset_check: slink_capset_check,
+ capset_set: slink_capset_set,
+ acct: slink_acct,
+ sysctl: slink_sysctl,
+ capable: slink_capable,
+ sys_security: slink_sys_security,
+ swapon: slink_swapon,
+ swapoff: slink_swapoff,
+ nfsservctl: slink_nfsservctl,
+ quotactl: slink_quotactl,
+ quota_on: slink_quota_on,
+ bdflush: slink_bdflush,
+ syslog: slink_syslog,
+ netlink_send: slink_netlink_send,
+ netlink_recv: slink_netlink_recv,
+
+ bprm_ops: &slink_binprm_ops,
+ sb_ops: &slink_sb_ops,
+ inode_ops: &slink_inode_ops,
+ file_ops: &slink_file_ops,
+ task_ops: &slink_task_ops,
+ socket_ops: &slink_socket_ops,
+ skb_ops: &slink_skb_ops,
+ ip_ops: &slink_ip_ops,
+ netdev_ops: &slink_netdev_ops,
+ module_ops: &slink_module_ops,
+ ipc_ops: &slink_ipc_ops,
+ msg_msg_ops: &slink_msg_ops,
+ msg_queue_ops: &slink_msg_queue_ops,
+ shm_ops: &slink_shm_ops,
+ sem_ops: &slink_sem_ops,
+
+ register_security: slink_register,
+ unregister_security: slink_unregister,
+};
+
+#if defined(CONFIG_SECURITY_SLINK_MODULE)
+#define MODULE_NAME THIS_MODULE->name
+#else
+#define MODULE_NAME "slink"
+#endif
+
+static int __init slink_init (void)
+{
+ /* register ourselves with the security framework */
+ if (register_security (&slink_ops)) {
+ printk (KERN_INFO
+ "Failure registering slink module with the kernel\n");
+ /* try registering with primary module */
+ if (mod_reg_security (MODULE_NAME, &slink_ops)) {
+ printk (KERN_INFO "Failure registering slink module "
+ "with primary security module.\n");
+ return -EINVAL;
+ }
+ secondary = 1;
+ }
+ printk(KERN_INFO "LSM/OpenWall: slink initialized\n");
+ return 0;
+}
+
+static void __exit slink_exit (void)
+{
+ /* remove ourselves from the security framework */
+ if (secondary) {
+ if (mod_unreg_security (MODULE_NAME, &slink_ops))
+ printk (KERN_INFO "Failure unregistering slink module "
+ "with primary module.\n");
+ return;
+ }
+
+ if (unregister_security (&slink_ops)) {
+ printk (KERN_INFO
+ "Failure unregistering slink module with the kernel\n");
+ }
+}
+
+module_init (slink_init);
+module_exit (slink_exit);
+
+MODULE_DESCRIPTION("LSM implementation of the Openwall kernel patch adding SECURE_LINK to link and follow_link");
+MODULE_LICENSE("GPL");
+