[LWN Logo]
[LWN.net]
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");
+