Aufs compatibility

Discuss and suggest new grsecurity features

Moderators: spender, PaX Team

Aufs compatibility

Postby wakizashi » Wed Oct 24, 2012 3:32 am

Hello, all!

I'm trying to use GRSECURITY with AUFS-enabled kernel (working just fine for me, and I really need it) and after patching it with GRSECURITY getting following errors, even with grsecurity disabled:
- Cut -
fs/aufs/dynop.c: In function ‘dy_aop’:
fs/aufs/dynop.c:179:2: error: assignment of member ‘writepage’ in read-only object
fs/aufs/dynop.c:180:2: error: assignment of member ‘readpage’ in read-only object
fs/aufs/dynop.c:181:2: error: assignment of member ‘writepages’ in read-only object
fs/aufs/dynop.c:182:2: error: assignment of member ‘set_page_dirty’ in read-only object
fs/aufs/dynop.c:183:2: error: assignment of member ‘readpages’ in read-only object
fs/aufs/dynop.c:184:2: error: assignment of member ‘write_begin’ in read-only object
fs/aufs/dynop.c:185:2: error: assignment of member ‘write_end’ in read-only object
fs/aufs/dynop.c:186:2: error: assignment of member ‘bmap’ in read-only object
fs/aufs/dynop.c:187:2: error: assignment of member ‘invalidatepage’ in read-only object
fs/aufs/dynop.c:188:2: error: assignment of member ‘releasepage’ in read-only object
fs/aufs/dynop.c:189:2: error: assignment of member ‘freepage’ in read-only object
fs/aufs/dynop.c:191:2: error: assignment of member ‘direct_IO’ in read-only object
fs/aufs/dynop.c:192:2: error: assignment of member ‘get_xip_mem’ in read-only object
fs/aufs/dynop.c:193:2: error: assignment of member ‘migratepage’ in read-only object
fs/aufs/dynop.c:194:2: error: assignment of member ‘launder_page’ in read-only object
fs/aufs/dynop.c:195:2: error: assignment of member ‘is_partially_uptodate’ in read-only object
fs/aufs/dynop.c:196:2: error: assignment of member ‘error_remove_page’ in read-only object
fs/aufs/dynop.c:197:2: error: assignment of member ‘swap_activate’ in read-only object
fs/aufs/dynop.c:198:2: error: assignment of member ‘swap_deactivate’ in read-only object
fs/aufs/dynop.c: In function ‘dy_adx’:
fs/aufs/dynop.c:272:3: error: assignment of member ‘direct_IO’ in read-only object
fs/aufs/dynop.c:273:3: error: assignment of member ‘get_xip_mem’ in read-only object
fs/aufs/dynop.c:275:3: error: assignment of member ‘direct_IO’ in read-only object
fs/aufs/dynop.c:276:3: error: assignment of member ‘get_xip_mem’ in read-only object
fs/aufs/dynop.c:278:4: error: assignment of member ‘get_xip_mem’ in read-only object
- Cut -

That happens both with 3.2.32 and 3.6.3 kernels (stable and testing branches of GRSECURITY).

Currently I've found that aufs (according to Documentation/filesystems/aufs/design/10dynop.txt) need to redefine operations in struct "address_space_operations", which by default is not const, but something in GRSECURITY makes it const, and I was not able to find - where it happens.

Unfortunately, I'm not that familiar with kernel source code to fix it mysef, does anybody know, how to fix it?

BTW, aufs source taken from latest git at aufs.sourceforge.net.

GRSECURITY have really good features, but this issue prevents it's usage on Live-like systems with aufs (For example, my linux system is loading from squashfs image at secured standalone workstation, with no changes allowed to be done by anybody, except the admin, who creating squashfs image).

Thanks in advance,
Alex
wakizashi
 
Posts: 3
Joined: Wed Oct 24, 2012 2:45 am

Re: Aufs compatibility

Postby PaX Team » Sat Oct 27, 2012 8:41 am

i think these days both Arch Linux and Gentoo have patches for this issue.
PaX Team
 
Posts: 2310
Joined: Mon Mar 18, 2002 4:35 pm

Re: Aufs compatibility

Postby wakizashi » Mon Oct 29, 2012 11:48 am

Unfortunately, no. It's too recent change in GRSECURITY.

That change in GRSECURITY is relatively new - as in 3.5.x kernels and in 3.2.2x it worked fine with AUFS.
AUFS not changed for these 2 months...
wakizashi
 
Posts: 3
Joined: Wed Oct 24, 2012 2:45 am

Re: Aufs compatibility

Postby PaX Team » Mon Oct 29, 2012 1:32 pm

wakizashi wrote:Unfortunately, no. It's too recent change in GRSECURITY.

That change in GRSECURITY is relatively new - as in 3.5.x kernels and in 3.2.2x it worked fine with AUFS.
AUFS not changed for these 2 months...
hm, nothing related changed in PaX recently. the gcc plugin based constify feature is over a year old now and that's what aufs runs into here.
PaX Team
 
Posts: 2310
Joined: Mon Mar 18, 2002 4:35 pm

Re: Aufs compatibility

Postby wakizashi » Thu Nov 08, 2012 1:21 pm

Hmm... Yes, you right, it's related to GCC plugin(constify_plugin), enabled by GRSECURITY.
So, that is what changed :)
If it's "over a year old" - why it worked fine with 3.5.3?

BTW, crazy workaround - typedefing with "__no_const" fixed that in AUFS code.
Strange, but direct use of __no_const in the structure field is not working...

Thanks a lot for the hint!

Regards,
Alex
wakizashi
 
Posts: 3
Joined: Wed Oct 24, 2012 2:45 am

Re: Aufs compatibility

Postby PaX Team » Thu Nov 08, 2012 5:06 pm

wakizashi wrote:Hmm... Yes, you right, it's related to GCC plugin(constify_plugin), enabled by GRSECURITY.
So, that is what changed :)
If it's "over a year old" - why it worked fine with 3.5.3?
either you didn't enable the CONSTIFY feature or you didn't have a plugin capable gcc at the time ;), otherwise there's no way aufs could have compiled.
BTW, crazy workaround - typedefing with "__no_const" fixed that in AUFS code.
i don't think that'll do what you think it does. you're cheating only the compiler that way, but the kernel runtime will still enforce the read-only property on these ops structures and aufs will cause an oops the moment it tries to modify them. the proper solution is what that patches in Arch/Gentoo do, that is, open/close the kernel around these modification attempts.
Strange, but direct use of __no_const in the structure field is not working...
that attribute is meaningful on structure types only (including structure fields of structure types), not arbitrary types. i should probably add a warning on other uses ;).
PaX Team
 
Posts: 2310
Joined: Mon Mar 18, 2002 4:35 pm

Re: Aufs compatibility

Postby korc » Tue Nov 05, 2013 1:19 am

I have been using aufs with grsecurity up to recently quite successfully with following patch, but unfortunately mmap patch conflicts with grsecurity and aufs has made mmap mandatory since 20131014.
patch which worked with 3.11.6 (and should work with aufs3-standalone 0cbc0bb1)
Code: Select all
diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
index 2f8888d..b9a0227 100644
--- a/fs/aufs/branch.h
+++ b/fs/aufs/branch.h
@@ -68,10 +68,11 @@ struct au_br_hfsnotify {
 };
 #endif
 
+typedef struct attribute __no_const attribute_no_const;
 /* sysfs entries */
 struct au_brsysfs {
    char         name[16];
-   struct attribute   attr;
+   attribute_no_const   attr;
 };
 
 enum {
diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c
index e13563e..8ba65ce 100644
--- a/fs/aufs/dynop.c
+++ b/fs/aufs/dynop.c
@@ -146,6 +146,17 @@ void au_dy_put(struct au_dykey *key)
 #define DyDbgInc(cnt)      do {} while (0)
 #endif
 
+#define AuGrsecPaxPtr(func, dst, src) do {      \
+   union {                  \
+      const void *o;            \
+      char **p;            \
+   } u;                  \
+   BUILD_BUG_ON(sizeof(u.o) != sizeof(&dst.func));   \
+   BUILD_BUG_ON(sizeof(*u.p) != sizeof(src.func));   \
+   u.o = (void *)&dst.func;         \
+   *u.p = (void *)src.func;         \
+} while (0)
+
 #define DySet(func, dst, src, h_op, h_sb) do {            \
    DyDbgInc(cnt);                     \
    if (h_op->func) {                  \
@@ -159,7 +170,7 @@ void au_dy_put(struct au_dykey *key)
 #define DySetForce(func, dst, src) do {      \
    AuDebugOn(!src.func);         \
    DyDbgInc(cnt);            \
-   dst.func = src.func;         \
+   AuGrsecPaxPtr(func, dst, src);      \
 } while (0)
 
 #define DySetAop(func) \
@@ -269,14 +280,21 @@ out:
  */
 static void dy_adx(struct au_dyaop *dyaop, int do_dx)
 {
+   union {
+      void *direct_IO, *get_xip_mem;
+   } grsec_pax_dummy = {
+      .get_xip_mem = NULL
+   };
+
    if (!do_dx) {
-      dyaop->da_op.direct_IO = NULL;
-      dyaop->da_op.get_xip_mem = NULL;
+      AuGrsecPaxPtr(direct_IO, dyaop->da_op, grsec_pax_dummy);
+      AuGrsecPaxPtr(get_xip_mem, dyaop->da_op, grsec_pax_dummy);
    } else {
-      dyaop->da_op.direct_IO = aufs_aop.direct_IO;
-      dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
+      AuGrsecPaxPtr(direct_IO, dyaop->da_op, aufs_aop);
+      AuGrsecPaxPtr(get_xip_mem, dyaop->da_op, aufs_aop);
       if (!dyaop->da_get_xip_mem)
-         dyaop->da_op.get_xip_mem = NULL;
+         AuGrsecPaxPtr(get_xip_mem, dyaop->da_op,
+                  grsec_pax_dummy);
    }
 }
 
diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
index 722152b..f55504b 100644
--- a/fs/aufs/sysfs.c
+++ b/fs/aufs/sysfs.c
@@ -227,7 +227,7 @@ void sysaufs_br_init(struct au_branch *br)
 {
    int i;
    struct au_brsysfs *br_sysfs;
-   struct attribute *attr;
+   attribute_no_const *attr;
 
    br_sysfs = br->br_sysfs;
    for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
korc
 
Posts: 4
Joined: Tue Nov 05, 2013 1:06 am

Re: Aufs compatibility

Postby PaX Team » Thu Nov 07, 2013 5:43 pm

korc wrote:I have been using aufs with grsecurity up to recently quite successfully with following patch, but unfortunately mmap patch conflicts with grsecurity and aufs has made mmap mandatory since 20131014.
forgive my ignorance, but what is the 'mmap patch' exactly?
PaX Team
 
Posts: 2310
Joined: Mon Mar 18, 2002 4:35 pm

Re: Aufs compatibility

Postby korc » Sat Nov 09, 2013 12:24 am

PaX Team wrote:forgive my ignorance, but what is the 'mmap patch' exactly?


It's one of the kernel patches in stand-alone version of aufs3 (namely aufs3-mmap.patch), which makes kernel to show aufs-based file paths, instead of lower branch-level file paths in /proc/$pid/maps. Previously it was optional, but because of a bug it has been made mandatory since e20834ec.
korc
 
Posts: 4
Joined: Tue Nov 05, 2013 1:06 am

Re: Aufs compatibility

Postby PaX Team » Sat Nov 16, 2013 11:44 am

i see, so someone will have to do ungrateful job of merging this with grsec ;).
PaX Team
 
Posts: 2310
Joined: Mon Mar 18, 2002 4:35 pm

Re: Aufs compatibility

Postby korc » Tue Nov 19, 2013 9:49 am

PaX Team wrote:i see, so someone will have to do ungrateful job of merging this with grsec ;).


Well, beers on me, that's for sure ;)
korc
 
Posts: 4
Joined: Tue Nov 05, 2013 1:06 am

Re: Aufs compatibility

Postby laurentius77 » Mon Dec 23, 2013 8:32 am

korc wrote:
PaX Team wrote:i see, so someone will have to do ungrateful job of merging this with grsec ;).


Well, beers on me, that's for sure ;)


Hello,

I'm also interested in having grsecurity compatible with AUFS3.

Did you manage to merging the patches?

Thank you.
laurentius77
 
Posts: 1
Joined: Mon Dec 23, 2013 8:28 am

Re: Aufs compatibility

Postby korc » Thu Jul 24, 2014 4:59 pm

I'm also interested in having grsecurity compatible with AUFS3.

Did you manage to merging the patches?

Thank you.


Succeeded. At the end, that wasn't that difficult with a little help from git and meld.
Process is something as following:
Code: Select all
mkdir -p $kern_loc ; tar xfJ $kern_txz --strip-components=1 -C $kern_loc ; cd $kern_loc
git init; git add -A;git commit -m vanilla
git branch grsec vanilla; git checkout grsec; patch -p1 <$grsec_patch
git add -A ; git commit -m grsec
git branch aufs vanilla ; git checkout aufs; for patch in $aufs_base $aufs_mmap $aufs_standalone;do patch -p1 <$patch ;done
git add -A ; git commit -m aufs
git merge grsec ; git mergetool --tool=meld  ## at this point you need to solve some conflicts, basically just preferring grsec stuff and applying aufs additions where needed seems to be fine
make menuconfig && make deb-pkg  # or whatever you need to build it
cd $aufs_location ; make KDIR="$kern_loc" INSTALL_MOD_STRIP=1 aufs.ko  # or install with INSTALL_MOD_PATH set to somewhere


final patch for aufs came out as following:
(have to be applied after grsec patch, and i haven't really tested it, so maybe it doesn't produce a good kernel at all)
Code: Select all
diff --git a/aufs3-mmap.patch b/aufs3-mmap.patch
index 3a30ba9..8490991 100644
--- a/aufs3-mmap.patch
+++ b/aufs3-mmap.patch
@@ -51,7 +51,7 @@ index fb52b54..3993b53 100644
     if (file) {
 +      file = vma_pr_or_file(vma);
        seq_printf(m, " file=");
-       seq_path(m, &file->f_path, "\n\t= ");
+       seq_path(m, &file->f_path, "\n\t\\= ");
     } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
 diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
 index 678455d..0ef7ef4 100644
@@ -174,9 +174,9 @@ index c1b7414..da6a011 100644
 +#define vma_get_file(vma)      vma_do_get_file(vma, __func__, __LINE__)
 +#define vma_fput(vma)         vma_do_fput(vma, __func__, __LINE__)
 +
- extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
- extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
-       void *buf, int len, int write);
+ extern ssize_t access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, size_t len, int write);
+ extern ssize_t access_remote_vm(struct mm_struct *mm, unsigned long addr,
+       void *buf, size_t len, int write);
 diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
 index 290901a..c21588b 100644
 --- a/include/linux/mm_types.h
@@ -201,15 +201,15 @@ diff --git a/kernel/fork.c b/kernel/fork.c
 index a17621c..40d9f6a 100644
 --- a/kernel/fork.c
 +++ b/kernel/fork.c
-@@ -412,7 +412,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
-          struct inode *inode = file_inode(file);
-          struct address_space *mapping = file->f_mapping;
+@@ -432,7 +432,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+       struct inode *inode = file_inode(file);
+       struct address_space *mapping = file->f_mapping;
 
--         get_file(file);
-+         vma_get_file(tmp);
-          if (tmp->vm_flags & VM_DENYWRITE)
-             atomic_dec(&inode->i_writecount);
-          mutex_lock(&mapping->i_mmap_mutex);
+-      get_file(file);
++      vma_get_file(tmp);
+       if (tmp->vm_flags & VM_DENYWRITE)
+          atomic_dec(&inode->i_writecount);
+       mutex_lock(&mapping->i_mmap_mutex);
 diff --git a/mm/filemap.c b/mm/filemap.c
 index 7a13f6a..f1805df 100644
 --- a/mm/filemap.c
@@ -340,15 +340,15 @@ index 20ff0c3..f743033 100644
 
     if (new->vm_ops && new->vm_ops->open)
        new->vm_ops->open(new);
-@@ -2448,7 +2448,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
+@@ -2883,7 +2883,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
     if (new->vm_ops && new->vm_ops->close)
        new->vm_ops->close(new);
     if (new->vm_file)
 -      fput(new->vm_file);
 +      vma_fput(new);
-    unlink_anon_vmas(new);
   out_free_mpol:
     mpol_put(vma_policy(new));
+  out_free_vma:
 @@ -2837,7 +2837,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
           if (anon_vma_clone(new_vma, vma))
              goto out_free_mempol;
diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
index 8e952e2..50e21b8 100644
--- a/fs/aufs/branch.h
+++ b/fs/aufs/branch.h
@@ -67,10 +67,11 @@ struct au_br_hfsnotify {
 };
 #endif
 
+typedef struct attribute __no_const attribute_no_const;
 /* sysfs entries */
 struct au_brsysfs {
    char         name[16];
-   struct attribute   attr;
+   attribute_no_const   attr;
 };
 
 enum {
diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c
index 58c7f5a..9f76e9e 100644
--- a/fs/aufs/dynop.c
+++ b/fs/aufs/dynop.c
@@ -145,11 +145,22 @@ void au_dy_put(struct au_dykey *key)
 #define DyDbgInc(cnt)      do {} while (0)
 #endif
 
+#define AuGrsecPaxPtr(func, dst, src) do {      \
+   union {                  \
+      const void *o;            \
+      char **p;            \
+   } u;                  \
+   BUILD_BUG_ON(sizeof(u.o) != sizeof(&dst.func));   \
+   BUILD_BUG_ON(sizeof(*u.p) != sizeof(src.func));   \
+   u.o = (void *)&dst.func;         \
+   *u.p = (void *)src.func;         \
+} while (0)
+
 #define DySet(func, dst, src, h_op, h_sb) do {            \
    DyDbgInc(cnt);                     \
    if (h_op->func) {                  \
       if (src.func)                  \
-         dst.func = src.func;            \
+         AuGrsecPaxPtr(func, dst, src);         \
       else                     \
          AuDbg("%s %s\n", au_sbtype(h_sb), #func);   \
    }                        \
@@ -158,7 +169,7 @@ void au_dy_put(struct au_dykey *key)
 #define DySetForce(func, dst, src) do {      \
    AuDebugOn(!src.func);         \
    DyDbgInc(cnt);            \
-   dst.func = src.func;         \
+   AuGrsecPaxPtr(func, dst, src);      \
 } while (0)
 
 #define DySetAop(func) \
@@ -268,14 +279,21 @@ out:
  */
 static void dy_adx(struct au_dyaop *dyaop, int do_dx)
 {
+   union {
+      void *direct_IO, *get_xip_mem;
+   } grsec_pax_dummy = {
+      .get_xip_mem = NULL
+   };
+
    if (!do_dx) {
-      dyaop->da_op.direct_IO = NULL;
-      dyaop->da_op.get_xip_mem = NULL;
+      AuGrsecPaxPtr(direct_IO, dyaop->da_op, grsec_pax_dummy);
+      AuGrsecPaxPtr(get_xip_mem, dyaop->da_op, grsec_pax_dummy);
    } else {
-      dyaop->da_op.direct_IO = aufs_aop.direct_IO;
-      dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
+      AuGrsecPaxPtr(direct_IO, dyaop->da_op, aufs_aop);
+      AuGrsecPaxPtr(get_xip_mem, dyaop->da_op, aufs_aop);
       if (!dyaop->da_get_xip_mem)
-         dyaop->da_op.get_xip_mem = NULL;
+         AuGrsecPaxPtr(get_xip_mem, dyaop->da_op,
+                  grsec_pax_dummy);
    }
 }
 
diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
index 8e97f8f..9d7e763 100644
--- a/fs/aufs/sysfs.c
+++ b/fs/aufs/sysfs.c
@@ -302,7 +302,7 @@ void sysaufs_br_init(struct au_branch *br)
 {
    int i;
    struct au_brsysfs *br_sysfs;
-   struct attribute *attr;
+   attribute_no_const *attr;
 
    br_sysfs = br->br_sysfs;
    for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
korc
 
Posts: 4
Joined: Tue Nov 05, 2013 1:06 am


Return to grsecurity development

cron