Index: linux-2.6.11-rsbac-v1.2.4/include/rsbac/adf.h
===================================================================
--- linux-2.6.11-rsbac-v1.2.4/include/rsbac/adf.h	(Revision 362)
+++ linux-2.6.11-rsbac-v1.2.4/include/rsbac/adf.h	(Arbeitskopie)
@@ -72,7 +72,10 @@
 extern int rsbac_sec_trunc(struct dentry * dentry_p,
                            loff_t new_len, loff_t old_len);
 
-extern void rsbac_symlink_redirect(struct dentry * dentry_p, char * name);
+char * rsbac_symlink_redirect(
+  struct dentry * dentry_p,
+  const char * name,
+  u_int maxlen);
 
 #ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
 extern int rsbac_dac_part_disabled(struct dentry * dentry_p);
Index: linux-2.6.11-rsbac-v1.2.4/fs/ext2/symlink.c
===================================================================
--- linux-2.6.11-rsbac-v1.2.4/fs/ext2/symlink.c	(Revision 362)
+++ linux-2.6.11-rsbac-v1.2.4/fs/ext2/symlink.c	(Arbeitskopie)
@@ -21,30 +21,10 @@
 #include "xattr.h"
 #include <linux/namei.h>
 
-/* RSBAC */
-#ifdef CONFIG_RSBAC_SYM_REDIR
-#include <linux/slab.h>
-#include <rsbac/adf.h>
-#endif
-
 static int ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct ext2_inode_info *ei = EXT2_I(dentry->d_inode);
-
-#ifdef CONFIG_RSBAC_SYM_REDIR
-        char * rsbac_name;
-
-	/* copying is ugly, but we must not change the const */
-	rsbac_name = __getname();
-	if(!rsbac_name)
-	  return -ENOMEM;
-	strcpy(rsbac_name, (char *)ei->i_data);
-        rsbac_symlink_redirect(dentry, rsbac_name);
-	nd_set_link(nd, rsbac_name);
-        putname(rsbac_name);
-#else
 	nd_set_link(nd, (char *)ei->i_data);
-#endif
 	return 0;
 }
 
Index: linux-2.6.11-rsbac-v1.2.4/fs/ext3/symlink.c
===================================================================
--- linux-2.6.11-rsbac-v1.2.4/fs/ext3/symlink.c	(Revision 362)
+++ linux-2.6.11-rsbac-v1.2.4/fs/ext3/symlink.c	(Arbeitskopie)
@@ -23,29 +23,10 @@
 #include <linux/namei.h>
 #include "xattr.h"
 
-/* RSBAC */
-#ifdef CONFIG_RSBAC_SYM_REDIR
-#include <linux/slab.h>
-#include <rsbac/adf.h>
-#endif
-
 static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-#ifdef CONFIG_RSBAC_SYM_REDIR
-        char * rsbac_name;
-
-	/* copying is ugly, but we must not change the const */
-	rsbac_name = __getname();
-	if(!rsbac_name)
-	  return -ENOMEM;
-	strcpy(rsbac_name, (char *)ei->i_data);
-        rsbac_symlink_redirect(dentry, rsbac_name);
-	nd_set_link(nd, rsbac_name);
-        putname(rsbac_name);
-#else
 	nd_set_link(nd, (char *)ei->i_data);
-#endif
 	return 0;
 }
 
Index: linux-2.6.11-rsbac-v1.2.4/fs/namei.c
===================================================================
--- linux-2.6.11-rsbac-v1.2.4/fs/namei.c	(Revision 362)
+++ linux-2.6.11-rsbac-v1.2.4/fs/namei.c	(Arbeitskopie)
@@ -505,8 +505,20 @@
 	error = dentry->d_inode->i_op->follow_link(dentry, nd);
 	if (!error) {
 		char *s = nd_get_link(nd);
-		if (s)
+		if (s) {
+		        #ifdef CONFIG_RSBAC_SYM_REDIR
+		        char * rsbac_name;
+
+                        rsbac_name = rsbac_symlink_redirect(dentry, s, PAGE_SIZE);
+			if(rsbac_name)
+			  {
+			    error = __vfs_follow_link(nd, rsbac_name);
+                            kfree(rsbac_name);
+                          }
+                        else
+			#endif
 			error = __vfs_follow_link(nd, s);
+                }
 		if (dentry->d_inode->i_op->put_link)
 			dentry->d_inode->i_op->put_link(dentry, nd);
 	}
@@ -3172,6 +3184,9 @@
 int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
 {
 	int len;
+        #ifdef CONFIG_RSBAC_SYM_REDIR
+        char * rsbac_name;
+        #endif
 
 	len = PTR_ERR(link);
 	if (IS_ERR(link))
@@ -3180,8 +3195,21 @@
 	len = strlen(link);
 	if (len > (unsigned) buflen)
 		len = buflen;
+
+        #ifdef CONFIG_RSBAC_SYM_REDIR
+        rsbac_name = rsbac_symlink_redirect(dentry, link, buflen);
+        if(rsbac_name)
+          {
+            len = strlen(rsbac_name);
+	    if (copy_to_user(buffer, rsbac_name, len))
+		len = -EFAULT;
+            kfree(rsbac_name);
+          }
+        else
+        #endif
 	if (copy_to_user(buffer, link, len))
 		len = -EFAULT;
+
 out:
 	return len;
 }
@@ -3239,9 +3267,6 @@
 	char *s = page_getlink(dentry, &page);
 	int res;
 
-#ifdef CONFIG_RSBAC_SYM_REDIR
-        rsbac_symlink_redirect(dentry, s);
-#endif
 	res = vfs_readlink(dentry,buffer,buflen,s);
 	if (page) {
 		kunmap(page);
@@ -3255,9 +3280,6 @@
 	struct page *page;
 	char *s = page_getlink(dentry, &page);
 
-#ifdef CONFIG_RSBAC_SYM_REDIR
-        rsbac_symlink_redirect(dentry, s);
-#endif
 	nd_set_link(nd, s);
 	return 0;
 }
Index: linux-2.6.11-rsbac-v1.2.4/rsbac/adf/adf_main.c
===================================================================
--- linux-2.6.11-rsbac-v1.2.4/rsbac/adf/adf_main.c	(Revision 362)
+++ linux-2.6.11-rsbac-v1.2.4/rsbac/adf/adf_main.c	(Arbeitskopie)
@@ -2715,57 +2715,49 @@
 #ifdef CONFIG_RSBAC_SYM_REDIR
 EXPORT_SYMBOL(rsbac_symlink_redirect);
 
-void rsbac_symlink_redirect(struct dentry * dentry_p, char * name)
+/* This function changes the symlink content by adding a suffix, if
+ * requested. It returns NULL, if unchanged, or a pointer to a
+ * kmalloc'd new char * otherwise, which has to be kfree'd after use.
+ */
+char * rsbac_symlink_redirect(
+  struct dentry * dentry_p,
+  const char * name,
+  u_int maxlen)
   {
     int                            err;
     union rsbac_target_id_t        i_tid;
+    char                         * new_name = NULL;
 #if defined(CONFIG_RSBAC_SYM_REDIR_MAC) || defined(CONFIG_RSBAC_SYM_REDIR_RC)
     union rsbac_target_id_t        i_tid2;
 #endif
     union rsbac_attribute_value_t  i_attr_val;
 
-    if(!name || !dentry_p || !dentry_p->d_inode)
-      return;
+    if(!name)
+      return NULL;
+    if(!dentry_p || !dentry_p->d_inode)
+      return NULL;
     if (!rsbac_is_initialized())
-      return;
+      return NULL;
 
-    i_tid.symlink.device = dentry_p->d_inode->i_sb->s_dev;
-    i_tid.symlink.inode = dentry_p->d_inode->i_ino;
-    i_tid.symlink.dentry_p = dentry_p;
     if(!S_ISLNK(dentry_p->d_inode->i_mode))
       {
-#ifdef CONFIG_RSBAC_RMSG
         rsbac_printk(KERN_DEBUG
                "rsbac_symlink_redirect(): called for non-symlink inode %u on dev %02u:%02u!\n",
                i_tid.symlink.inode,
                RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
-#endif
-#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
-        if (!rsbac_nosyslog)
-#endif
-        printk(KERN_DEBUG
-               "rsbac_symlink_redirect(): called for non-symlink inode %u on dev %02u:%02u!\n",
-               i_tid.symlink.inode,
-               RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
-        return;
+        return NULL;
       }
 
+    i_tid.symlink.device = dentry_p->d_inode->i_sb->s_dev;
+    i_tid.symlink.inode = dentry_p->d_inode->i_ino;
+    i_tid.symlink.dentry_p = dentry_p;
 #ifdef CONFIG_RSBAC_DEBUG
     if (rsbac_debug_aef)
       {
-#ifdef CONFIG_RSBAC_RMSG
         rsbac_printk(KERN_DEBUG
                "rsbac_symlink_redirect(): called for symlink inode %u on dev %02u:%02u!\n",
                i_tid.symlink.inode,
                RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
-#endif
-#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
-        if (!rsbac_nosyslog)
-#endif
-        printk(KERN_DEBUG
-               "rsbac_symlink_redirect(): called for symlink inode %u on dev %02u:%02u!\n",
-               i_tid.symlink.inode,
-               RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
       }
 #endif
 
@@ -2778,7 +2770,13 @@
                               FALSE) ))
       {
         rsbac_ds_get_error("rsbac_symlink_redirect()", A_symlink_add_uid);
-        return;  /* something weird happened */
+        if(new_name)
+          kfree(new_name);
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %u on dev %02u:%02u!\n",
+               i_tid.symlink.inode,
+               RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+        return NULL;  /* something weird happened */
       }
     if(i_attr_val.symlink_add_uid)
       {
@@ -2791,10 +2789,33 @@
               && (name[len-1] <= '9')
              )
           len--;
-        if(len > (PAGE_SIZE - 20))
-          return;
+        if(len > (maxlen - 20))
+          {
+            if(new_name)
+              kfree(new_name);
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %u on dev %02u:%02u!\n",
+               i_tid.symlink.inode,
+               RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+            return NULL;
+          }
         if(!rsbac_get_owner(&user))
-          ulongtostr(name+len, user);
+          {
+            if(!new_name)
+              {
+                new_name = kmalloc(maxlen, GFP_KERNEL);
+                if(!new_name)
+                  {
+                    rsbac_printk(KERN_DEBUG
+                                 "rsbac_symlink_redirect(): could not allocate memory for redirection of inode %u on dev %02u:%02u!\n",
+                                 i_tid.symlink.inode,
+                                 RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+                    return NULL;
+                  }
+                strcpy(new_name, name);
+              }
+            ulongtostr(new_name+len, user);
+          }
       }
 #endif
 
@@ -2807,7 +2828,9 @@
                               FALSE) ))
       {
         rsbac_ds_get_error("rsbac_symlink_redirect()", A_symlink_add_mac_level);
-        return;  /* something weird happened */
+        if(new_name)
+          kfree(new_name);
+        return NULL;  /* something weird happened */
       }
     if(i_attr_val.symlink_add_mac_level)
       {
@@ -2825,11 +2848,19 @@
              )
           len--;
 #ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
-        if(len > (PAGE_SIZE - 85))
+        if(len > (maxlen - 85))
 #else
-        if(len > (PAGE_SIZE - 20))
+        if(len > (maxlen - 20))
 #endif
-          return;
+          {
+            if(new_name)
+              kfree(new_name);
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %u on dev %02u:%02u!\n",
+               i_tid.symlink.inode,
+               RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+            return NULL;
+          }
 
         i_tid2.process = current->pid;
         if ((err = rsbac_get_attr(MAC,
@@ -2840,13 +2871,28 @@
                                   FALSE) ))
           {
             rsbac_ds_get_error("rsbac_symlink_redirect()", A_current_sec_level);
-            return;  /* something weird happened */
+            if(new_name)
+              kfree(new_name);
+            return NULL;  /* something weird happened */
           }
 
+        if(!new_name)
+          {
+            new_name = kmalloc(maxlen, GFP_KERNEL);
+            if(!new_name)
+              {
+                rsbac_printk(KERN_DEBUG
+                             "rsbac_symlink_redirect(): could not allocate memory for redirection of inode %u on dev %02u:%02u!\n",
+                             i_tid.symlink.inode,
+                             RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+                return NULL;
+              }
+            strcpy(new_name, name);
+          }
 #ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
-        len+=sprintf(name+len, "%u:", i_attr_val.current_sec_level);
+        len+=sprintf(new_name+len, "%u:", i_attr_val.current_sec_level);
 #else
-        len+=sprintf(name+len, "%u", i_attr_val.current_sec_level);
+        len+=sprintf(new_name+len, "%u", i_attr_val.current_sec_level);
 #endif
 
 #ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
@@ -2858,9 +2904,11 @@
                                   FALSE) ))
           {
             rsbac_ds_get_error("rsbac_symlink_redirect()", A_mac_curr_categories);
-            return;  /* something weird happened */
+            if(new_name)
+              kfree(new_name);
+            return NULL;  /* something weird happened */
           }
-        u64tostrmac(name+len, i_attr_val.mac_categories);
+        u64tostrmac(new_name+len, i_attr_val.mac_categories);
 #endif
       }
 #endif
@@ -2874,7 +2922,9 @@
                               FALSE) ))
       {
         rsbac_ds_get_error("rsbac_symlink_redirect()", A_symlink_add_rc_role);
-        return;  /* something weird happened */
+        if(new_name)
+          kfree(new_name);
+        return NULL;  /* something weird happened */
       }
     if(i_attr_val.symlink_add_rc_role)
       {
@@ -2886,8 +2936,16 @@
               && (name[len-1] <= '9')
              )
           len--;
-        if(len > (PAGE_SIZE - 20))
-          return;
+        if(len > (maxlen - 20))
+          {
+            if(new_name)
+              kfree(new_name);
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %u on dev %02u:%02u!\n",
+               i_tid.symlink.inode,
+               RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+            return NULL;
+          }
 
         i_tid2.process = current->pid;
         if ((err = rsbac_get_attr(RC,
@@ -2898,14 +2956,29 @@
                                   FALSE) ))
           {
             rsbac_ds_get_error("rsbac_symlink_redirect()", A_rc_role);
-            return;  /* something weird happened */
+            if(new_name)
+              kfree(new_name);
+            return NULL;  /* something weird happened */
           }
 
-        ulongtostr(name+len, i_attr_val.rc_role);
+        if(!new_name)
+          {
+            new_name = kmalloc(maxlen, GFP_KERNEL);
+            if(!new_name)
+              {
+                rsbac_printk(KERN_DEBUG
+                             "rsbac_symlink_redirect(): could not allocate memory for redirection of inode %u on dev %02u:%02u!\n",
+                             i_tid.symlink.inode,
+                             RSBAC_MAJOR(i_tid.symlink.device), RSBAC_MINOR(i_tid.symlink.device) );
+                return NULL;
+              }
+            strcpy(new_name, name);
+          }
+        ulongtostr(new_name+len, i_attr_val.rc_role);
       }
 #endif
 
-    return;
+    return new_name;
   }
 #endif
 
Index: linux-2.6.11-rsbac-v1.2.4/rsbac/data_structures/aci_data_structures.c
===================================================================
--- linux-2.6.11-rsbac-v1.2.4/rsbac/data_structures/aci_data_structures.c	(Revision 362)
+++ linux-2.6.11-rsbac-v1.2.4/rsbac/data_structures/aci_data_structures.c	(Arbeitskopie)
@@ -14305,7 +14305,18 @@
                   read_lock(&tasklist_lock);
                   task_p = find_task_by_pid(tid_p->process);
                   if(task_p)
-                    value->pax_flags = task_p->flags & RSBAC_PAX_ALL_FLAGS;
+                    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+  #if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
+                      if(task_p->mm)
+                        value->pax_flags = task_p->mm->flags & RSBAC_PAX_ALL_FLAGS;
+                      else
+  #endif
+                        value->pax_flags = 0;
+#else
+                      value->pax_flags = task_p->flags & RSBAC_PAX_ALL_FLAGS;
+#endif
+                    }
                   else
                     err = -RSBAC_EINVALIDTARGET;
                   read_unlock(&tasklist_lock);
