[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Grsec/PaX and Exec-shield



> Also note that I use LSM on all my kernels, so anything that conflicts with 
> LSM is something that I have no ability to test and therefore no interest in 
> maintaining.  I'm sure I could get PaX working with LSM, but it would take 
> some work.  Anyway I'll look into this matter after I upload an exec-shield 
> package.

I've spared you your precious time and gone ahead and done this for you.  
Funny thing is that the latest version of LSM for 2.4 is still at 
2.4.20.  Trying to patch a clean 2.4.22 kernel with this results in 
rejects in 9 files.  Here're the contents of the rejects:

***************
*** 329,335 ****
  };

  #define MAY_PTRACE(p) \
- (p==current||(p->p_pptr==current&&(p->ptrace & 
PT_PTRACED)&&p->state==TASK_STOPPED))


  static int mem_open(struct inode* inode, struct file* file)
--- 329,335 ----
  };

  #define MAY_PTRACE(p) \
+ (p==current||(p->p_pptr==current&&(p->ptrace & 
PT_PTRACED)&&p->state==TASK_STOPPED&&security_ops->ptrace(current,p)==0))


  static int mem_open(struct inode* inode, struct file* file)
***************
*** 1418,1423 ****
                if (!sb)
                        goto out;
        }

        ret = -EINVAL;
        switch (cmds) {
--- 1421,1430 ----
                if (!sb)
                        goto out;
        }
+
+       ret = security_ops->quotactl (cmds, type, id, sb);
+       if (ret)
+               goto out;

        ret = -EINVAL;
        switch (cmds) {
***************
*** 75,86 ****

  static kmem_cache_t * inode_cachep;

- #define alloc_inode() \
-        ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))
  static void destroy_inode(struct inode *inode)
  {
        if (inode_has_buffers(inode))
                BUG();
        kmem_cache_free(inode_cachep, (inode));
  }

--- 76,101 ----

  static kmem_cache_t * inode_cachep;

+ static inline struct inode *alloc_inode(void)
+ {
+       struct inode *inode;
+
+       inode = ((struct inode *) kmem_cache_alloc(inode_cachep, 
SLAB_KERNEL));
+       if (!inode)
+               return NULL;
+       inode->i_security = NULL;
+       if (security_ops->inode_alloc_security(inode)) {
+               kmem_cache_free(inode_cachep, (inode));
+               return NULL;
+       }
+       return inode;
+ }
+
  static void destroy_inode(struct inode *inode)
  {
        if (inode_has_buffers(inode))
                BUG();
+       security_ops->inode_free_security(inode);
        kmem_cache_free(inode_cachep, (inode));
  }

***************
*** 27,32 ****
  #include <linux/devfs_fs_kernel.h>
  #include <linux/major.h>
  #include <linux/acct.h>

  #include <asm/uaccess.h>

--- 27,33 ----
  #include <linux/devfs_fs_kernel.h>
  #include <linux/major.h>
  #include <linux/acct.h>
+ #include <linux/security.h>

  #include <asm/uaccess.h>

***************
*** 1044,1063 ****

  asmlinkage long sys_sethostname(char *name, int len)
  {
        int errno;

        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
        down_write(&uts_sem);
-       errno = -EFAULT;
-       if (!copy_from_user(system_utsname.nodename, name, len)) {
-               system_utsname.nodename[len] = 0;
-               errno = 0;
-       }
        up_write(&uts_sem);
-       return errno;
  }

  asmlinkage long sys_gethostname(char *name, int len)
--- 1043,1067 ----

  asmlinkage long sys_sethostname(char *name, int len)
  {
+       char nodename[__NEW_UTS_LEN+1];
        int errno;

        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
+       if (copy_from_user(nodename, name, len))
+               return -EFAULT;
+       nodename[len] = 0;
+
+       errno = security_ops->sethostname(nodename);
+       if (errno)
+               return errno;
+
        down_write(&uts_sem);
+       memcpy(system_utsname.nodename, nodename, len+1);
        up_write(&uts_sem);
+       return 0;
  }

  asmlinkage long sys_gethostname(char *name, int len)
***************
*** 1083,1101 ****
   */
  asmlinkage long sys_setdomainname(char *name, int len)
  {
        int errno;

        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;

        down_write(&uts_sem);
-       errno = -EFAULT;
-       if (!copy_from_user(system_utsname.domainname, name, len)) {
-               errno = 0;
-               system_utsname.domainname[len] = 0;
-       }
        up_write(&uts_sem);
        return errno;
  }
--- 1087,1109 ----
   */
  asmlinkage long sys_setdomainname(char *name, int len)
  {
+       char domainname[__NEW_UTS_LEN+1];
        int errno;

        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
+       if (copy_from_user(domainname, name, len))
+               return -EFAULT;
+       domainname[len] = 0;
+
+       errno = security_ops->setdomainname(domainname);
+       if (errno)
+               return errno;

        down_write(&uts_sem);
+       memcpy(system_utsname.domainname, domainname, len+1);
        up_write(&uts_sem);
        return errno;
  }
***************
*** 1177,1191 ****

  static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff 
*skb)
  {
        /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
           number of warnings when compiling with -W --ANK
         */
        if (atomic_read(&sk->rmem_alloc) + skb->truesize >= 
(unsigned)sk->rcvbuf)
                  return -ENOMEM;

  #ifdef CONFIG_FILTER
        if (sk->filter) {
-               int err = 0;
                struct sk_filter *filter;

                /* It would be deadlock, if sock_queue_rcv_skb is used
--- 1192,1211 ----

  static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff 
*skb)
  {
+       int err = 0;
+
        /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
           number of warnings when compiling with -W --ANK
         */
        if (atomic_read(&sk->rmem_alloc) + skb->truesize >= 
(unsigned)sk->rcvbuf)
                  return -ENOMEM;

+       err = security_ops->socket_sock_rcv_skb(sk, skb);
+       if (err)
+               return err;
+
  #ifdef CONFIG_FILTER
        if (sk->filter) {
                struct sk_filter *filter;

                /* It would be deadlock, if sock_queue_rcv_skb is used
***************
*** 62,67 ****
  #include <linux/spinlock.h>
  #include <linux/init.h>
  #include <linux/proc_fs.h>
  #include <asm/uaccess.h>
  #include "util.h"

--- 62,68 ----
  #include <linux/spinlock.h>
  #include <linux/init.h>
  #include <linux/proc_fs.h>
+ #include <linux/security.h>
  #include <asm/uaccess.h>
  #include "util.h"

***************
*** 455,458 ****

  endmenu

  source lib/Config.in
--- 455,459 ----

  endmenu

+ source security/Config.in
  source lib/Config.in
***************
*** 1,7 ****
  VERSION = 2
  PATCHLEVEL = 4
  SUBLEVEL = 20
- EXTRAVERSION =

  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

--- 1,7 ----
  VERSION = 2
  PATCHLEVEL = 4
  SUBLEVEL = 20
+ EXTRAVERSION = -lsm1

  KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)

***************
*** 121,131 ****

  #export RAMDISK = -DRAMDISK=512

- CORE_FILES    =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
  NETWORKS      =net/network.o

  LIBS          =$(TOPDIR)/lib/lib.a
- SUBDIRS               =kernel drivers mm fs net ipc lib

  DRIVERS-n :=
  DRIVERS-y :=
--- 121,131 ----

  #export RAMDISK = -DRAMDISK=512

+ CORE_FILES    =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o 
security/vmlinux-obj.o
  NETWORKS      =net/network.o

  LIBS          =$(TOPDIR)/lib/lib.a
+ SUBDIRS               =kernel drivers mm fs net ipc lib security

  DRIVERS-n :=
  DRIVERS-y :=

--------------------------------------------------------------------------

Patching the latest release of PaX onto this kernel results in ONE 
additional reject (arch/ia64/config.in) :

***************
*** 291,293 ****
  fi

  endmenu
--- 291,322 ----
  fi

  endmenu
+
+ mainmenu_option next_comment
+ comment 'PaX options'
+
+ bool 'Enforce non-executable pages' CONFIG_PAX_NOEXEC
+ if [ "$CONFIG_PAX_NOEXEC" = "y" ]; then
+    bool 'Paging based non-executable pages' CONFIG_PAX_PAGEEXEC
+    if [ "$CONFIG_PAX_PAGEEXEC" = "y" ]; then
+ #      bool '  Emulate trampolines' CONFIG_PAX_EMUTRAMP
+ #      if [ "$CONFIG_PAX_EMUTRAMP" = "y" ]; then
+ #         bool '    Automatically emulate sigreturn trampolines' 
CONFIG_PAX_EMUSIGRT
+ #      fi
+       bool '  Restrict mprotect()' CONFIG_PAX_MPROTECT
+       if [ "$CONFIG_PAX_MPROTECT" = "y" ]; then
+          bool '    Disallow ELF text relocations' 
CONFIG_PAX_NOELFRELOCS
+ #         bool '    Automatically emulate ELF PLT' CONFIG_PAX_EMUPLT
+ #         bool '    Allow ELF ET_EXEC text relocations' 
CONFIG_PAX_ETEXECRELOCS
+       fi
+    fi
+ fi
+ bool 'Address Space Layout Randomization' CONFIG_PAX_ASLR
+ if [ "$CONFIG_PAX_ASLR" = "y" ]; then
+    bool '  Randomize user stack base' CONFIG_PAX_RANDUSTACK
+    bool '  Randomize mmap() base' CONFIG_PAX_RANDMMAP
+    if [ "$CONFIG_PAX_RANDMMAP" = "y" -a "$CONFIG_PAX_PAGEEXEC" = "y" 
]; then
+       bool '  Randomize ET_EXEC base' CONFIG_PAX_RANDEXEC
+    fi
+ fi
+ endmenu


Now surely, Russell, a "security expert" such as yourself is capable of 
copy+pasting that last reject in the file.  Doing this took one minute.  
I would imagine this was much less time than it took for you to write 
your ignorant mails complaining about things you don't understand or 
haven't bothered to try yourself.

Also, I think both you and Ingo will be interested to see the results of 
a bugfixed version of paxtest.  Are you so certain that Exec-shield 
stops execution in shared library bss/data?  Or did you just say it 
because that's what a program told you?  Do you want to change your 
answer before it's released?  Or can you tell me why Exec-shield will 
prevent execution in those areas?  If you can tell my why, I'll be sure 
to tell you why it doesn't, and why it's impossible for it to.

It's pretty funny that there's a claim that Exec-shield doesn't break 
binary compatibility, since it seems Redhat "invented" a new binary 
standard.  I don't ever recall any discussion of this "standard" before 
it was committed.  PT_GNU_STACK defines when an application requires an 
executable stack or not.  So I wonder what happens when someone tries to 
run tuxracer on a system that doesn't use PT_GNU_STACK?  Will 
Exec-shield then break "binary compatibility" without the presence of 
its self-made "standard"?

It's fun to learn new things!

-Brad



Reply to: