Re: new xattr handler as syscall replacement

From: Christoph Klein (christophk@private-karlsruhe.de)
Date: Thu Sep 15 2005 - 01:56:21 PDT


Hi,
Seems like i was not clear enough. But anynway i found a solution to my
problem, without changing kernel sources. I post it here FYI. The
following code changes the xattr handler in the superblock structure to
install its own namespace.

Chris

/* virtual xattr stuff */


#define NGACL_XATTR_PREFIX "ngacl."
#define NGACL_XATTR_UID_SUFFIX "uid"

#define for_each_xattr_handler(handlers, handler)               \
                for ((handler) = *(handlers)++;                 \
                        (handler) != NULL;                      \
                        (handler) = *(handlers)++)

size_t ngacl_xattr_list(struct inode *inode, char *list, size_t
list_size, const char *name, size_t name_len) {
        printk(KERN_INFO "ngacl_list\n");
        return 0;
}

int ngacl_xattr_get(struct inode *inode, const char *name, void *buffer,
size_t size) {
        printk(KERN_INFO "ngacl_get\n");

        const char *subname;
        subname = name;
        subname = subname + strlen(NGACL_XATTR_PREFIX);
        printk(KERN_INFO "with name %s\n", subname);
        if (!(strncmp(name,
NGACL_XATTR_UID_SUFFIX,strlen(NGACL_XATTR_UID_SUFFIX) -1))) {
                /* Check if buffer is long enough
                it should be (sizeof(uid_t) / 3) +1 */
                if (buffer == NULL) {
                        return (sizeof(uid_t) / 3) +1;
                } else if (size < ((sizeof(inode->i_uid) / 3) +1)) {
                        return -ERANGE;
                }
                return snprintf(buffer,size,"%u",inode->i_uid);
        }

        return -EINVAL;
}

int ngacl_xattr_set(struct inode *inode, const char *name, const void
*buffer, size_t size, int flags) {
        printk(KERN_INFO "ngacl_set\n");
        const char *subname;
        subname = name;
        subname = subname + strlen(NGACL_XATTR_PREFIX);
        printk(KERN_INFO "with name %s\n", subname);
        if (!(strncmp(name,
NGACL_XATTR_UID_SUFFIX,strlen(NGACL_XATTR_UID_SUFFIX) -1))) {
                struct iattr attr;
                struct dentry *dentry;
                char *endp;
                endp = buffer + size;
                uid_t owner;
                ngacl_dbg(debug, "this is an owner for us!\n");
                owner = simple_strtoul(buffer, &endp,10);
                ngacl_dbg(debug,"and his uid is %u\n",owner);
                attr.ia_valid = ATTR_UID | ATTR_FORCE;
                attr.ia_uid = owner;
                dentry = d_find_alias(inode);
                if (dentry == NULL) {
                        return -EINVAL;
                }
                notify_change(dentry,&attr);
                return 0;
        }
        return -EINVAL;
}

struct xattr_handler ngacl_xattr_handler = {
        .prefix = NGACL_XATTR_PREFIX,
        .list = ngacl_xattr_list,
        .get = ngacl_xattr_get,
        .set = ngacl_xattr_set,
};



int ngacl_sb_kern_mount(struct super_block *sb, void *data) {

        int entries=0;
        int i,alloc_size=0;
        struct xattr_handler **old_handlers, **new_handlers, **handlers,
*old_handler;



        old_handlers = sb->s_xattr;


        if (sb == NULL) {
                goto out;
        }
        if (sb->s_xattr == NULL) {
                goto out;
        }

        for_each_xattr_handler(old_handlers, old_handler) {
                entries++;
        }

        if ( entries == 0 ) {
                goto out;
        }

        alloc_size=(entries+2)*(sizeof(old_handler));
        printk(KERN_INFO "%i\n", alloc_size);
        handlers=kmalloc(alloc_size, GFP_KERNEL);
        if (handlers == NULL) {
                printk(KERN_INFO "handlers is null\n");
        }
        new_handlers = handlers;


        old_handlers=sb->s_xattr;


        for_each_xattr_handler(old_handlers, old_handler) {
                *new_handlers = old_handler;
                printk(KERN_INFO "Copying %s %s\n", old_handler->prefix,
(*new_handlers)->prefix);
                *(new_handlers)++;
        }
        *new_handlers = &ngacl_xattr_handler;
        *(new_handlers)++;
        *new_handlers = NULL;

        sb->s_xattr = handlers;

        old_handlers=handlers;
        for_each_xattr_handler(old_handlers, old_handler) {
                printk(KERN_INFO "Newmember: %s\n",
old_handler->prefix);
        }

        printk(KERN_INFO "kern_mount out %i\n", entries);

        out:

        return 0;

}



This archive was generated by hypermail 2.1.3 : Thu Sep 15 2005 - 01:56:53 PDT