Commit bd997c62 authored by Nathan Scott's avatar Nathan Scott

[XFS] Add the security extended attributes namespace.

SGI Modid: xfs-linux:xfs-kern:165638a
parent 20bc7252
...@@ -60,6 +60,14 @@ ...@@ -60,6 +60,14 @@
# define set_posix_acl_flag(sb) do { } while (0) # define set_posix_acl_flag(sb) do { } while (0)
#endif #endif
#ifdef CONFIG_XFS_SECURITY
# define XFS_SECURITY_STRING "security attrs, "
# define ENOSECURITY 0
#else
# define XFS_SECURITY_STRING
# define ENOSECURITY EOPNOTSUPP
#endif
#ifdef CONFIG_XFS_RT #ifdef CONFIG_XFS_RT
# define XFS_REALTIME_STRING "realtime, " # define XFS_REALTIME_STRING "realtime, "
#else #else
...@@ -89,6 +97,7 @@ ...@@ -89,6 +97,7 @@
#endif #endif
#define XFS_BUILD_OPTIONS XFS_ACL_STRING \ #define XFS_BUILD_OPTIONS XFS_ACL_STRING \
XFS_SECURITY_STRING \
XFS_REALTIME_STRING \ XFS_REALTIME_STRING \
XFS_BIGFS_STRING \ XFS_BIGFS_STRING \
XFS_TRACE_STRING \ XFS_TRACE_STRING \
......
...@@ -2587,6 +2587,14 @@ attr_trusted_capable( ...@@ -2587,6 +2587,14 @@ attr_trusted_capable(
return 0; return 0;
} }
STATIC int
attr_secure_capable(
struct vnode *vp,
cred_t *cred)
{
return -ENOSECURITY;
}
STATIC int STATIC int
attr_system_set( attr_system_set(
struct vnode *vp, char *name, void *data, size_t size, int xflags) struct vnode *vp, char *name, void *data, size_t size, int xflags)
...@@ -2650,6 +2658,16 @@ struct attrnames attr_trusted = { ...@@ -2650,6 +2658,16 @@ struct attrnames attr_trusted = {
.attr_capable = attr_trusted_capable, .attr_capable = attr_trusted_capable,
}; };
struct attrnames attr_secure = {
.attr_name = "security.",
.attr_namelen = sizeof("security.") - 1,
.attr_flag = ATTR_SECURE,
.attr_get = attr_generic_get,
.attr_set = attr_generic_set,
.attr_remove = attr_generic_remove,
.attr_capable = attr_secure_capable,
};
struct attrnames attr_user = { struct attrnames attr_user = {
.attr_name = "user.", .attr_name = "user.",
.attr_namelen = sizeof("user.") - 1, .attr_namelen = sizeof("user.") - 1,
...@@ -2660,4 +2678,4 @@ struct attrnames attr_user = { ...@@ -2660,4 +2678,4 @@ struct attrnames attr_user = {
}; };
struct attrnames *attr_namespaces[] = struct attrnames *attr_namespaces[] =
{ &attr_system, &attr_trusted, &attr_user }; { &attr_system, &attr_trusted, &attr_secure, &attr_user };
...@@ -69,8 +69,9 @@ typedef struct attrnames { ...@@ -69,8 +69,9 @@ typedef struct attrnames {
attrcapable_t attr_capable; attrcapable_t attr_capable;
} attrnames_t; } attrnames_t;
#define ATTR_NAMECOUNT 3 #define ATTR_NAMECOUNT 4
extern struct attrnames attr_user; extern struct attrnames attr_user;
extern struct attrnames attr_secure;
extern struct attrnames attr_system; extern struct attrnames attr_system;
extern struct attrnames attr_trusted; extern struct attrnames attr_trusted;
extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
...@@ -86,6 +87,7 @@ extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *); ...@@ -86,6 +87,7 @@ extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ #define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ #define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
#define ATTR_TRUST 0x0004 /* -- unused, from IRIX -- */ #define ATTR_TRUST 0x0004 /* -- unused, from IRIX -- */
#define ATTR_SECURE 0x0008 /* use attrs in security namespace */
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ #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_REPLACE 0x0020 /* pure set: fail if attr does not exist */
#define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */ #define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */
......
...@@ -159,6 +159,9 @@ xfs_attr_shortform_add(xfs_da_args_t *args) ...@@ -159,6 +159,9 @@ xfs_attr_shortform_add(xfs_da_args_t *args)
continue; continue;
if (memcmp(args->name, sfe->nameval, args->namelen) != 0) if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
continue; continue;
if (((args->flags & ATTR_SECURE) != 0) !=
((sfe->flags & XFS_ATTR_SECURE) != 0))
continue;
if (((args->flags & ATTR_ROOT) != 0) != if (((args->flags & ATTR_ROOT) != 0) !=
((sfe->flags & XFS_ATTR_ROOT) != 0)) ((sfe->flags & XFS_ATTR_ROOT) != 0))
continue; continue;
...@@ -173,7 +176,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args) ...@@ -173,7 +176,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args)
sfe->namelen = args->namelen; sfe->namelen = args->namelen;
INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen); INT_SET(sfe->valuelen, ARCH_CONVERT, args->valuelen);
sfe->flags = (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; sfe->flags = (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
memcpy(sfe->nameval, args->name, args->namelen); memcpy(sfe->nameval, args->name, args->namelen);
memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen); memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
INT_MOD(sf->hdr.count, ARCH_CONVERT, 1); INT_MOD(sf->hdr.count, ARCH_CONVERT, 1);
...@@ -209,6 +213,9 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) ...@@ -209,6 +213,9 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
continue; continue;
if (memcmp(sfe->nameval, args->name, args->namelen) != 0) if (memcmp(sfe->nameval, args->name, args->namelen) != 0)
continue; continue;
if (((args->flags & ATTR_SECURE) != 0) !=
((sfe->flags & XFS_ATTR_SECURE) != 0))
continue;
if (((args->flags & ATTR_ROOT) != 0) != if (((args->flags & ATTR_ROOT) != 0) !=
((sfe->flags & XFS_ATTR_ROOT) != 0)) ((sfe->flags & XFS_ATTR_ROOT) != 0))
continue; continue;
...@@ -253,6 +260,9 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args) ...@@ -253,6 +260,9 @@ xfs_attr_shortform_lookup(xfs_da_args_t *args)
continue; continue;
if (memcmp(args->name, sfe->nameval, args->namelen) != 0) if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
continue; continue;
if (((args->flags & ATTR_SECURE) != 0) !=
((sfe->flags & XFS_ATTR_SECURE) != 0))
continue;
if (((args->flags & ATTR_ROOT) != 0) != if (((args->flags & ATTR_ROOT) != 0) !=
((sfe->flags & XFS_ATTR_ROOT) != 0)) ((sfe->flags & XFS_ATTR_ROOT) != 0))
continue; continue;
...@@ -281,6 +291,9 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args) ...@@ -281,6 +291,9 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args)
continue; continue;
if (memcmp(args->name, sfe->nameval, args->namelen) != 0) if (memcmp(args->name, sfe->nameval, args->namelen) != 0)
continue; continue;
if (((args->flags & ATTR_SECURE) != 0) !=
((sfe->flags & XFS_ATTR_SECURE) != 0))
continue;
if (((args->flags & ATTR_ROOT) != 0) != if (((args->flags & ATTR_ROOT) != 0) !=
((sfe->flags & XFS_ATTR_ROOT) != 0)) ((sfe->flags & XFS_ATTR_ROOT) != 0))
continue; continue;
...@@ -369,7 +382,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) ...@@ -369,7 +382,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
nargs.valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT); nargs.valuelen = INT_GET(sfe->valuelen, ARCH_CONVERT);
nargs.hashval = xfs_da_hashname((char *)sfe->nameval, nargs.hashval = xfs_da_hashname((char *)sfe->nameval,
sfe->namelen); sfe->namelen);
nargs.flags = (sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; nargs.flags = (sfe->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
((sfe->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */
ASSERT(error == ENOATTR); ASSERT(error == ENOATTR);
error = xfs_attr_leaf_add(bp, &nargs); error = xfs_attr_leaf_add(bp, &nargs);
...@@ -446,14 +460,15 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) ...@@ -446,14 +460,15 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
attrnames_t *namesp; attrnames_t *namesp;
namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
&attr_user;
if (((context->flags & ATTR_ROOT) != 0) != if (((context->flags & ATTR_ROOT) != 0) !=
((sfe->flags & XFS_ATTR_ROOT) != 0) && ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
!(context->flags & ATTR_KERNFULLS)) { !(context->flags & ATTR_KERNFULLS)) {
sfe = XFS_ATTR_SF_NEXTENTRY(sfe); sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
continue; continue;
} }
namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure:
((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
&attr_user);
if (context->flags & ATTR_KERNOVAL) { if (context->flags & ATTR_KERNOVAL) {
ASSERT(context->flags & ATTR_KERNAMELS); ASSERT(context->flags & ATTR_KERNAMELS);
context->count += namesp->attr_namelen + context->count += namesp->attr_namelen +
...@@ -548,8 +563,9 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) ...@@ -548,8 +563,9 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
for ( ; i < nsbuf; i++, sbp++) { for ( ; i < nsbuf; i++, sbp++) {
attrnames_t *namesp; attrnames_t *namesp;
namesp = (sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted : namesp = (sfe->flags & XFS_ATTR_SECURE) ? &attr_secure :
&attr_user; ((sfe->flags & XFS_ATTR_ROOT) ? &attr_trusted :
&attr_user);
if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) { if (cursor->hashval != INT_GET(sbp->hash, ARCH_CONVERT)) {
cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT); cursor->hashval = INT_GET(sbp->hash, ARCH_CONVERT);
...@@ -668,7 +684,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args) ...@@ -668,7 +684,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args)
nargs.value = (char *)&name_loc->nameval[nargs.namelen]; nargs.value = (char *)&name_loc->nameval[nargs.namelen];
nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT); nargs.valuelen = INT_GET(name_loc->valuelen, ARCH_CONVERT);
nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT); nargs.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
nargs.flags = (entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0; nargs.flags = (entry->flags & XFS_ATTR_SECURE) ? ATTR_SECURE :
((entry->flags & XFS_ATTR_ROOT) ? ATTR_ROOT : 0);
xfs_attr_shortform_add(&nargs); xfs_attr_shortform_add(&nargs);
} }
error = 0; error = 0;
...@@ -963,7 +980,8 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) ...@@ -963,7 +980,8 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
+ INT_GET(map->size, ARCH_CONVERT)); + INT_GET(map->size, ARCH_CONVERT));
INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); INT_SET(entry->hashval, ARCH_CONVERT, args->hashval);
entry->flags = tmp ? XFS_ATTR_LOCAL : 0; entry->flags = tmp ? XFS_ATTR_LOCAL : 0;
entry->flags |= (args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0; entry->flags |= (args->flags & ATTR_SECURE) ? XFS_ATTR_SECURE :
((args->flags & ATTR_ROOT) ? XFS_ATTR_ROOT : 0);
if (args->rename) { if (args->rename) {
entry->flags |= XFS_ATTR_INCOMPLETE; entry->flags |= XFS_ATTR_INCOMPLETE;
if ((args->blkno2 == args->blkno) && if ((args->blkno2 == args->blkno) &&
...@@ -1881,6 +1899,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) ...@@ -1881,6 +1899,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
if (memcmp(args->name, (char *)name_loc->nameval, if (memcmp(args->name, (char *)name_loc->nameval,
args->namelen) != 0) args->namelen) != 0)
continue; continue;
if (((args->flags & ATTR_SECURE) != 0) !=
((entry->flags & XFS_ATTR_SECURE) != 0))
continue;
if (((args->flags & ATTR_ROOT) != 0) != if (((args->flags & ATTR_ROOT) != 0) !=
((entry->flags & XFS_ATTR_ROOT) != 0)) ((entry->flags & XFS_ATTR_ROOT) != 0))
continue; continue;
...@@ -1893,6 +1914,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) ...@@ -1893,6 +1914,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
if (memcmp(args->name, (char *)name_rmt->name, if (memcmp(args->name, (char *)name_rmt->name,
args->namelen) != 0) args->namelen) != 0)
continue; continue;
if (((args->flags & ATTR_SECURE) != 0) !=
((entry->flags & XFS_ATTR_SECURE) != 0))
continue;
if (((args->flags & ATTR_ROOT) != 0) != if (((args->flags & ATTR_ROOT) != 0) !=
((entry->flags & XFS_ATTR_ROOT) != 0)) ((entry->flags & XFS_ATTR_ROOT) != 0))
continue; continue;
...@@ -2290,8 +2314,9 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) ...@@ -2290,8 +2314,9 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
!(context->flags & ATTR_KERNFULLS)) !(context->flags & ATTR_KERNFULLS))
continue; /* skip non-matching entries */ continue; /* skip non-matching entries */
namesp = (entry->flags & XFS_ATTR_ROOT) ? &attr_trusted : namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
&attr_user; ((entry->flags & XFS_ATTR_ROOT) ? &attr_trusted :
&attr_user);
if (entry->flags & XFS_ATTR_LOCAL) { if (entry->flags & XFS_ATTR_LOCAL) {
name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i); name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
......
...@@ -73,9 +73,9 @@ struct xfs_trans; ...@@ -73,9 +73,9 @@ struct xfs_trans;
* to work "forw"ard. If none matches, continue with the "forw"ard leaf * to work "forw"ard. If none matches, continue with the "forw"ard leaf
* nodes until the hash key changes or the attribute name is found. * nodes until the hash key changes or the attribute name is found.
* *
* We store the fact that an attribute is a ROOT versus USER attribute in * We store the fact that an attribute is a ROOT/USER/SECURE attribute in
* the leaf_entry. The namespaces are independent only because we also look * the leaf_entry. The namespaces are independent only because we also look
* at the root/user bit when we are looking for a matching attribute name. * at the namespace bit when we are looking for a matching attribute name.
* *
* We also store a "incomplete" bit in the leaf_entry. It shows that an * We also store a "incomplete" bit in the leaf_entry. It shows that an
* attribute is in the middle of being created and should not be shown to * attribute is in the middle of being created and should not be shown to
...@@ -102,7 +102,7 @@ typedef struct xfs_attr_leafblock { ...@@ -102,7 +102,7 @@ typedef struct xfs_attr_leafblock {
struct xfs_attr_leaf_entry { /* sorted on key, not name */ struct xfs_attr_leaf_entry { /* sorted on key, not name */
xfs_dahash_t hashval; /* hash value of name */ xfs_dahash_t hashval; /* hash value of name */
__uint16_t nameidx; /* index into buffer of name/value */ __uint16_t nameidx; /* index into buffer of name/value */
__uint8_t flags; /* LOCAL, ROOT and INCOMPLETE flags */ __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
__uint8_t pad2; /* unused pad byte */ __uint8_t pad2; /* unused pad byte */
} entries[1]; /* variable sized array */ } entries[1]; /* variable sized array */
struct xfs_attr_leaf_name_local { struct xfs_attr_leaf_name_local {
...@@ -130,9 +130,11 @@ typedef struct xfs_attr_leaf_name_remote xfs_attr_leaf_name_remote_t; ...@@ -130,9 +130,11 @@ typedef struct xfs_attr_leaf_name_remote xfs_attr_leaf_name_remote_t;
*/ */
#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) #define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment