This is based on Tad 's security. handler for 2.4 diff -urN linux-2.6.0-test10.orig/fs/Kconfig linux-2.6.0-test10/fs/Kconfig --- linux-2.6.0-test10.orig/fs/Kconfig 2003-11-23 19:32:05.000000000 -0600 +++ linux-2.6.0-test10/fs/Kconfig 2003-11-26 09:38:46.000000000 -0600 @@ -355,6 +355,20 @@ If you don't know what Access Control Lists are, say N +config XFS_XATTR_SECURITY + bool "Security Labels" + depends on XFS_FS + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the XFS filesystem. + + Note: Enabling this option will break IRIX compatability. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. + config MINIX_FS tristate "Minix fs support" help diff -urN linux-2.6.0-test10.orig/fs/xfs/linux/xfs_iops.c linux-2.6.0-test10/fs/xfs/linux/xfs_iops.c --- linux-2.6.0-test10.orig/fs/xfs/linux/xfs_iops.c 2003-11-23 19:31:38.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/linux/xfs_iops.c 2003-11-26 00:47:25.000000000 -0600 @@ -561,10 +561,16 @@ #define SYSTEM_NAME "system." /* VFS shared names/values */ #define ROOT_NAME "trusted." /* root's own names/values */ #define USER_NAME "user." /* user's own names/values */ +#ifdef CONFIG_XFS_XATTR_SECURITY +#define SECURITY_NAME "security." /* security namespace */ +#endif STATIC xattr_namespace_t xfs_namespace_array[] = { { .name= SYSTEM_NAME, .namelen= sizeof(SYSTEM_NAME)-1,.exists= NULL }, { .name= ROOT_NAME, .namelen= sizeof(ROOT_NAME)-1, .exists= NULL }, { .name= USER_NAME, .namelen= sizeof(USER_NAME)-1, .exists= NULL }, +#ifdef CONFIG_XFS_XATTR_SECURITY + { .name= SECURITY_NAME, .namelen= sizeof(SECURITY_NAME)-1, .exists= NULL }, +#endif { .name= NULL } }; xattr_namespace_t *xfs_namespaces = &xfs_namespace_array[0]; @@ -667,6 +673,15 @@ VOP_ATTR_SET(vp, p, (void *) data, size, xflags, NULL, error); return -error; } +#ifdef CONFIG_XFS_XATTR_SECURITY + if (strncmp(name, xfs_namespaces[SECURITY_NAMES].name, + xfs_namespaces[SECURITY_NAMES].namelen) == 0) { + xflags |= ATTR_SECURITY; + p += xfs_namespaces[SECURITY_NAMES].namelen; + VOP_ATTR_SET(vp, p, (void *) data, size, xflags, NULL, error); + return -error; + } +#endif return -EOPNOTSUPP; } @@ -723,6 +738,17 @@ error = -size; return -error; } +#ifdef CONFIG_XFS_XATTR_SECURITY + if (strncmp(name, xfs_namespaces[SECURITY_NAMES].name, + xfs_namespaces[SECURITY_NAMES].namelen) == 0) { + xflags |= ATTR_SECURITY; + p += xfs_namespaces[SECURITY_NAMES].namelen; + VOP_ATTR_GET(vp, p, data, (int *)&size, xflags, NULL, error); + if (!error) + error = -size; + return -error; + } +#endif return -EOPNOTSUPP; } @@ -813,6 +839,15 @@ VOP_ATTR_REMOVE(vp, p, xflags, NULL, error); return -error; } +#ifdef CONFIG_XFS_XATTR_SECURITY + if (strncmp(name, xfs_namespaces[SECURITY_NAMES].name, + xfs_namespaces[SECURITY_NAMES].namelen) == 0) { + xflags |= ATTR_SECURITY; + p += xfs_namespaces[SECURITY_NAMES].namelen; + VOP_ATTR_REMOVE(vp, p, xflags, NULL, error); + return -error; + } +#endif return -EOPNOTSUPP; } diff -urN linux-2.6.0-test10.orig/fs/xfs/linux/xfs_iops.h linux-2.6.0-test10/fs/xfs/linux/xfs_iops.h --- linux-2.6.0-test10.orig/fs/xfs/linux/xfs_iops.h 2003-11-23 19:32:03.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/linux/xfs_iops.h 2003-11-26 00:51:19.000000000 -0600 @@ -53,6 +53,9 @@ #define SYSTEM_NAMES 0 #define ROOT_NAMES 1 #define USER_NAMES 2 +#ifdef CONFIG_XFS_XATTR_SECURITY +#define SECURITY_NAMES 3 +#endif extern struct xattr_namespace *xfs_namespaces; diff -urN linux-2.6.0-test10.orig/fs/xfs/xfs_attr.c linux-2.6.0-test10/fs/xfs/xfs_attr.c --- linux-2.6.0-test10.orig/fs/xfs/xfs_attr.c 2003-11-23 19:32:07.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/xfs_attr.c 2003-11-26 00:56:44.000000000 -0600 @@ -221,7 +221,11 @@ int local, size; uint nblks; xfs_mount_t *mp; +#ifdef CONFIG_XFS_XATTR_SECURITY + int rsvd = (flags & (ATTR_ROOT|ATTR_SECURITY)) != 0; +#else int rsvd = (flags & ATTR_ROOT) != 0; +#endif int namelen; ASSERT(MAXNAMELEN-1 <= 0xff); /* length is stored in uint8 */ @@ -545,8 +549,11 @@ * Root fork attributes can use reserved data blocks for this * operation if necessary */ - +#ifdef CONFIG_XFS_XATTR_SECURITY + if (flags & (ATTR_ROOT|ATTR_SECURITY)) +#else if (flags & ATTR_ROOT) +#endif args.trans->t_flags |= XFS_TRANS_RESERVE; if ((error = xfs_trans_reserve(args.trans, diff -urN linux-2.6.0-test10.orig/fs/xfs/xfs_attr.h linux-2.6.0-test10/fs/xfs/xfs_attr.h --- linux-2.6.0-test10.orig/fs/xfs/xfs_attr.h 2003-11-23 19:31:16.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/xfs_attr.h 2003-11-26 00:58:05.000000000 -0600 @@ -59,6 +59,9 @@ *========================================================================*/ #define ATTR_ROOT 0x0002 /* use attrs in root namespace, not user */ +#ifdef CONFIG_XFS_XATTR_SECURITY +#define ATTR_SECURITY 0x0004 /* use attrs in security namespace, not root/user */ +#endif #define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ #define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */ #define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */ diff -urN linux-2.6.0-test10.orig/fs/xfs/xfs_attr_leaf.c linux-2.6.0-test10/fs/xfs/xfs_attr_leaf.c --- linux-2.6.0-test10.orig/fs/xfs/xfs_attr_leaf.c 2003-11-23 19:31:54.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/xfs_attr_leaf.c 2003-11-26 09:26:37.000000000 -0600 @@ -159,8 +159,15 @@ continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; +#ifdef CONFIG_XFS_XATTR_SECURITY + if (((args->flags & ATTR_ROOT) != 0) != + ((sfe->flags & XFS_ATTR_ROOT) != 0) || + ((args->flags & ATTR_SECURITY) != 0) != + ((sfe->flags & XFS_ATTR_SECURITY) != 0)) +#else if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) +#endif continue; return(XFS_ERROR(EEXIST)); } @@ -174,6 +181,9 @@ sfe->namelen = args->namelen; INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen); sfe->flags = (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; +#ifdef CONFIG_XFS_XATTR_SECURITY + sfe->flags |= (args->flags & ATTR_SECURITY) ? XFS_ATTR_SECURITY : 0; +#endif memcpy(sfe->nameval, args->name, args->namelen); memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); INT_MOD(sf->hdr.count, ARCH_CONVERT, 1); @@ -209,8 +219,15 @@ continue; if (memcmp(sfe->nameval, args->name, args->namelen) != 0) continue; +#ifdef CONFIG_XFS_XATTR_SECURITY + if (((args->flags & ATTR_ROOT) != 0) != + ((sfe->flags & XFS_ATTR_ROOT) != 0) || + ((args->flags & ATTR_SECURITY) != 0) != + ((sfe->flags & XFS_ATTR_SECURITY) != 0)) +#else if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) +#endif continue; break; } @@ -253,8 +270,15 @@ continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; +#ifdef CONFIG_XFS_XATTR_SECURITY + if (((args->flags & ATTR_ROOT) != 0) != + ((sfe->flags & XFS_ATTR_ROOT) != 0) || + ((args->flags & ATTR_SECURITY) != 0) != + ((sfe->flags & XFS_ATTR_SECURITY) != 0)) +#else if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) +#endif continue; return(XFS_ERROR(EEXIST)); } @@ -281,8 +305,15 @@ continue; if (memcmp(args->name, sfe->nameval, args->namelen) != 0) continue; +#ifdef CONFIG_XFS_XATTR_SECURITY + if (((args->flags & ATTR_ROOT) != 0) != + ((sfe->flags & XFS_ATTR_ROOT) != 0) || + ((args->flags & ATTR_SECURITY) != 0) != + ((sfe->flags & XFS_ATTR_SECURITY) != 0)) +#else if (((args->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0)) +#endif continue; if (args->flags & ATTR_KERNOVAL) { args->valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); @@ -370,6 +401,9 @@ nargs.hashval = xfs_da_hashname((char *)sfe->nameval, sfe->namelen); nargs.flags = (sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; +#ifdef CONFIG_XFS_XATTR_SECURITY + nargs.flags |= (sfe->flags & XFS_ATTR_SECURITY) ? ATTR_SECURITY : 0; +#endif error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ ASSERT(error == ENOATTR); error = xfs_attr_leaf_add(bp, &nargs); @@ -444,10 +478,20 @@ < context->bufsize) { for (i = 0, sfe = &sf->list[0]; i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { +#ifdef CONFIG_XFS_XATTR_SECURITY + int ns = (sfe->flags & XFS_ATTR_ROOT)? ROOT_NAMES: + (sfe->flags & XFS_ATTR_SECURITY)? + SECURITY_NAMES:USER_NAMES; + if ((((context->flags & ATTR_ROOT) != 0) != + ((sfe->flags & XFS_ATTR_ROOT) != 0) || + ((context->flags & ATTR_SECURITY) != 0) != + ((sfe->flags & XFS_ATTR_SECURITY) != 0)) && +#else int ns = (sfe->flags & XFS_ATTR_ROOT)? ROOT_NAMES : USER_NAMES; if (((context->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0) && +#endif !(context->flags & ATTR_KERNFULLS)) { sfe = XFS_ATTR_SF_NEXTENTRY(sfe); continue; @@ -494,8 +538,15 @@ kmem_free(sbuf, sbsize); return XFS_ERROR(EFSCORRUPTED); } +#ifdef CONFIG_XFS_XATTR_SECURITY + if ((((context->flags & ATTR_ROOT) != 0) != + ((sfe->flags & XFS_ATTR_ROOT) != 0) || + ((context->flags & ATTR_SECURITY) != 0) != + ((sfe->flags & XFS_ATTR_SECURITY) != 0)) && +#else if (((context->flags & ATTR_ROOT) != 0) != ((sfe->flags & XFS_ATTR_ROOT) != 0) && +#endif !(context->flags & ATTR_KERNFULLS)) { sfe = XFS_ATTR_SF_NEXTENTRY(sfe); continue; @@ -544,7 +595,13 @@ * Loop putting entries into the user buffer. */ for ( ; i < nsbuf; i++, sbp++) { +#ifdef CONFIG_XFS_XATTR_SECURITY + int ns = (sbp->flags & XFS_ATTR_ROOT)? ROOT_NAMES: + (sbp->flags & XFS_ATTR_SECURITY)? + SECURITY_NAMES:USER_NAMES; +#else int ns = (sbp->flags & XFS_ATTR_ROOT)? ROOT_NAMES:USER_NAMES; +#endif if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) { cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT); cursor->offset = 0; @@ -663,6 +720,9 @@ nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT); nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); nargs.flags = (entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; +#ifdef CONFIG_XFS_XATTR_SECURITY + nargs.flags |= (entry->flags & XFS_ATTR_SECURITY) ? ATTR_SECURITY : 0; +#endif xfs_attr_shortform_add(&nargs); } error = 0; @@ -958,6 +1018,9 @@ INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); entry->flags = tmp ? XFS_ATTR_LOCAL : 0; entry->flags |= (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; +#ifdef CONFIG_XFS_XATTR_SECURITY + entry->flags |= (args->flags & ATTR_SECURITY) ? XFS_ATTR_SECURITY : 0; +#endif if (args->rename) { entry->flags |= XFS_ATTR_INCOMPLETE; if ((args->blkno2 == args->blkno) && @@ -1875,8 +1938,15 @@ if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0) continue; +#ifdef CONFIG_XFS_XATTR_SECURITY + if (((args->flags & ATTR_ROOT) != 0) != + ((entry->flags & XFS_ATTR_ROOT) != 0) || + ((args->flags & ATTR_SECURITY) != 0) != + ((entry->flags & XFS_ATTR_SECURITY) != 0)) +#else if (((args->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0)) +#endif continue; args->index = probe; return(XFS_ERROR(EEXIST)); @@ -1887,8 +1957,15 @@ if (memcmp(args->name, (char *)name_rmt->name, args->namelen) != 0) continue; +#ifdef CONFIG_XFS_XATTR_SECURITY + if (((args->flags & ATTR_ROOT) != 0) != + ((entry->flags & XFS_ATTR_ROOT) != 0) || + ((args->flags & ATTR_SECURITY) != 0) != + ((entry->flags & XFS_ATTR_SECURITY) != 0)) +#else if (((args->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0)) +#endif continue; args->index = probe; args->rmtblkno @@ -2270,7 +2347,13 @@ retval = 0; for ( ; (i < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (retval == 0); entry++, i++) { +#ifdef CONFIG_XFS_XATTR_SECURITY + int ns = (entry->flags & XFS_ATTR_ROOT)? ROOT_NAMES: + (entry->flags & XFS_ATTR_SECURITY)? + SECURITY_NAMES:USER_NAMES; +#else int ns = (entry->flags & XFS_ATTR_ROOT)? ROOT_NAMES:USER_NAMES; +#endif if (INT_GET(entry->hashval, ARCH_CONVERT) != cursor->hashval) { cursor->hashval = INT_GET(entry->hashval, ARCH_CONVERT); @@ -2279,8 +2362,15 @@ if (entry->flags & XFS_ATTR_INCOMPLETE) continue; /* skip incomplete entries */ +#ifdef CONFIG_XFS_XATTR_SECURITY + if ((((context->flags & ATTR_ROOT) != 0) != + ((entry->flags & XFS_ATTR_ROOT) != 0) || + ((context->flags & ATTR_SECURITY) != 0) != + ((entry->flags & XFS_ATTR_SECURITY) != 0)) && +#else if (((context->flags & ATTR_ROOT) != 0) != ((entry->flags & XFS_ATTR_ROOT) != 0) && +#endif !(context->flags & ATTR_KERNFULLS)) continue; /* skip non-matching entries */ diff -urN linux-2.6.0-test10.orig/fs/xfs/xfs_attr_leaf.h linux-2.6.0-test10/fs/xfs/xfs_attr_leaf.h --- linux-2.6.0-test10.orig/fs/xfs/xfs_attr_leaf.h 2003-11-23 19:30:55.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/xfs_attr_leaf.h 2003-11-26 09:27:50.000000000 -0600 @@ -129,9 +129,15 @@ */ #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ #define XFS_ATTR_ROOT_BIT 1 /* limit access to attr to userid 0 */ +#ifdef CONFIG_XFS_XATTR_SECURITY +#define XFS_ATTR_SECURITY_BIT 2 /* attr is in security.* namespace */ +#endif #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) +#ifdef CONFIG_XFS_XATTR_SECURITY +#define XFS_ATTR_SECURITY (1 << XFS_ATTR_SECURITY_BIT) +#endif #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) /* diff -urN linux-2.6.0-test10.orig/fs/xfs/xfsidbg.c linux-2.6.0-test10/fs/xfs/xfsidbg.c --- linux-2.6.0-test10.orig/fs/xfs/xfsidbg.c 2003-11-23 19:32:43.000000000 -0600 +++ linux-2.6.0-test10/fs/xfs/xfsidbg.c 2003-11-26 09:35:07.000000000 -0600 @@ -3313,9 +3313,17 @@ kdb_printf("LOCAL "); if (e->flags & XFS_ATTR_ROOT) kdb_printf("ROOT "); +#ifdef CONFIG_XFS_XATTR_SECURITY + if (e->flags & XFS_ATTR_SECURITY) + kdb_printf("SECURITY "); +#endif if (e->flags & XFS_ATTR_INCOMPLETE) kdb_printf("INCOMPLETE "); +#ifdef CONFIG_XFS_XATTR_SECURITY + k = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT | XFS_ATTR_SECURITY | XFS_ATTR_INCOMPLETE); +#else k = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT | XFS_ATTR_INCOMPLETE); +#endif if ((e->flags & k) != 0) kdb_printf("0x%x", e->flags & k); kdb_printf(">\n name \""); @@ -3703,13 +3711,21 @@ (uint_t)n->hashval, n->whichfork); if (n->flags & ATTR_ROOT) kdb_printf("ROOT "); +#ifdef CONFIG_XFS_XATTR_SECURITY + if (n->flags & ATTR_SECURITY) + kdb_printf("SECURITY "); +#endif if (n->flags & ATTR_CREATE) kdb_printf("CREATE "); if (n->flags & ATTR_REPLACE) kdb_printf("REPLACE "); if (n->flags & XFS_ATTR_INCOMPLETE) kdb_printf("INCOMPLETE "); +#ifdef CONFIG_XFS_XATTR_SECURITY + i = ~(ATTR_ROOT | ATTR_SECURITY | ATTR_CREATE | ATTR_REPLACE | XFS_ATTR_INCOMPLETE); +#else i = ~(ATTR_ROOT | ATTR_CREATE | ATTR_REPLACE | XFS_ATTR_INCOMPLETE); +#endif if ((n->flags & i) != 0) kdb_printf("0x%x", n->flags & i); kdb_printf(">\n");