X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fxattr.c;h=a9db225579983b4babe40ac4c47a9eef0a3250cb;hb=4c8d3d997ef3c0594350fba716529905b314287e;hp=6acd5c63da9113613132492dea834d8304554fd8;hpb=cb220c1af49644786944c549518b491d4c654030;p=linux-2.6-omap-h63xx.git diff --git a/fs/xattr.c b/fs/xattr.c index 6acd5c63da9..a9db2255799 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -51,22 +51,30 @@ setxattr(struct dentry *d, char __user *name, void __user *value, } } + down(&d->d_inode->i_sem); + error = security_inode_setxattr(d, kname, kvalue, size, flags); + if (error) + goto out; error = -EOPNOTSUPP; if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { - down(&d->d_inode->i_sem); - error = security_inode_setxattr(d, kname, kvalue, size, flags); - if (error) - goto out; - error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); + error = d->d_inode->i_op->setxattr(d, kname, kvalue, + size, flags); if (!error) { fsnotify_xattr(d); - security_inode_post_setxattr(d, kname, kvalue, size, flags); + security_inode_post_setxattr(d, kname, kvalue, + size, flags); } -out: - up(&d->d_inode->i_sem); + } else if (!strncmp(kname, XATTR_SECURITY_PREFIX, + sizeof XATTR_SECURITY_PREFIX - 1)) { + const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; + error = security_inode_setsecurity(d->d_inode, suffix, kvalue, + size, flags); + if (!error) + fsnotify_xattr(d); } - if (kvalue) - kfree(kvalue); +out: + up(&d->d_inode->i_sem); + kfree(kvalue); return error; } @@ -134,29 +142,37 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) if (size) { if (size > XATTR_SIZE_MAX) size = XATTR_SIZE_MAX; - kvalue = kmalloc(size, GFP_KERNEL); + kvalue = kzalloc(size, GFP_KERNEL); if (!kvalue) return -ENOMEM; } + error = security_inode_getxattr(d, kname); + if (error) + goto out; error = -EOPNOTSUPP; - if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { - error = security_inode_getxattr(d, kname); - if (error) - goto out; + if (d->d_inode->i_op && d->d_inode->i_op->getxattr) error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); - if (error > 0) { - if (size && copy_to_user(value, kvalue, error)) - error = -EFAULT; - } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { - /* The file system tried to returned a value bigger - than XATTR_SIZE_MAX bytes. Not possible. */ - error = -E2BIG; - } + + if (!strncmp(kname, XATTR_SECURITY_PREFIX, + sizeof XATTR_SECURITY_PREFIX - 1)) { + const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1; + int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue, + size, error); + /* Security module active: overwrite error value */ + if (rv != -EOPNOTSUPP) + error = rv; + } + if (error > 0) { + if (size && copy_to_user(value, kvalue, error)) + error = -EFAULT; + } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { + /* The file system tried to returned a value bigger + than XATTR_SIZE_MAX bytes. Not possible. */ + error = -E2BIG; } out: - if (kvalue) - kfree(kvalue); + kfree(kvalue); return error; } @@ -221,24 +237,27 @@ listxattr(struct dentry *d, char __user *list, size_t size) return -ENOMEM; } + error = security_inode_listxattr(d); + if (error) + goto out; error = -EOPNOTSUPP; if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { - error = security_inode_listxattr(d); - if (error) - goto out; error = d->d_inode->i_op->listxattr(d, klist, size); - if (error > 0) { - if (size && copy_to_user(list, klist, error)) - error = -EFAULT; - } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { - /* The file system tried to returned a list bigger - than XATTR_LIST_MAX bytes. Not possible. */ - error = -E2BIG; - } + } else { + error = security_inode_listsecurity(d->d_inode, klist, size); + if (size && error >= size) + error = -ERANGE; + } + if (error > 0) { + if (size && copy_to_user(list, klist, error)) + error = -EFAULT; + } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { + /* The file system tried to returned a list bigger + than XATTR_LIST_MAX bytes. Not possible. */ + error = -E2BIG; } out: - if (klist) - kfree(klist); + kfree(klist); return error; } @@ -307,6 +326,8 @@ removexattr(struct dentry *d, char __user *name) down(&d->d_inode->i_sem); error = d->d_inode->i_op->removexattr(d, kname); up(&d->d_inode->i_sem); + if (!error) + fsnotify_xattr(d); } out: return error;