Commit 3324836f authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: Put legacy OS/2 extended attributes in "os2." namespace

Existing OS/2 extended attributes are stored without a namespace
prefix.  To avoid polluting the linux namespace, prepend "os2." when
listing the EAs but store "os2." EA names without the prefix.

Also disallow setting extended attributes that don't begin with
"user." or "os2."
parent 8cf4ec99
......@@ -78,6 +78,68 @@ struct ea_buffer {
#define EA_NEW 0x0004
#define EA_MALLOC 0x0008
/* Namespaces */
#define XATTR_SYSTEM_PREFIX "system."
#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
#define XATTR_USER_PREFIX "user."
#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
#define XATTR_OS2_PREFIX "os2."
#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
/*
* These three routines are used to recognize on-disk extended attributes
* that are in a recognized namespace. If the attribute is not recognized,
* "os2." is prepended to the name
*/
static inline int is_os2_xattr(struct jfs_ea *ea)
{
/*
* Check for "system."
*/
if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) &&
!strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return FALSE;
/*
* Check for "user."
*/
if ((ea->namelen >= XATTR_USER_PREFIX_LEN) &&
!strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
return FALSE;
/*
* Add any other valid namespace prefixes here
*/
/*
* We assume it's OS/2's flat namespace
*/
return TRUE;
}
static inline int name_size(struct jfs_ea *ea)
{
if (is_os2_xattr(ea))
return ea->namelen + XATTR_OS2_PREFIX_LEN;
else
return ea->namelen;
}
static inline int copy_name(char *buffer, struct jfs_ea *ea)
{
int len = ea->namelen;
if (is_os2_xattr(ea)) {
memcpy(buffer, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN);
buffer += XATTR_OS2_PREFIX_LEN;
len += XATTR_OS2_PREFIX_LEN;
}
memcpy(buffer, ea->name, ea->namelen);
buffer[ea->namelen] = 0;
return len;
}
/* Forward references */
static void ea_release(struct inode *inode, struct ea_buffer *ea_buf);
......@@ -577,7 +639,8 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
return rc;
}
static int can_set_xattr(struct inode *inode, const char *name)
static int can_set_xattr(struct inode *inode, const char *name,
const void *value, size_t value_len)
{
if (IS_RDONLY(inode))
return -EROFS;
......@@ -585,6 +648,10 @@ static int can_set_xattr(struct inode *inode, const char *name)
if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode))
return -EPERM;
if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) &&
(strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0))
return -ENOTSUP;
if (!S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX))
return -EPERM;
......@@ -592,7 +659,7 @@ static int can_set_xattr(struct inode *inode, const char *name)
return permission(inode, MAY_WRITE);
}
int __jfs_setxattr(struct inode *inode, const char *name, void *value,
int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
size_t value_len, int flags)
{
struct jfs_ea_list *ealist;
......@@ -602,13 +669,24 @@ int __jfs_setxattr(struct inode *inode, const char *name, void *value,
int xattr_size;
int new_size;
int namelen = strlen(name);
char *os2name = NULL;
int found = 0;
int rc;
int length;
if ((rc = can_set_xattr(inode, name)))
if ((rc = can_set_xattr(inode, name, value, value_len)))
return rc;
if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
GFP_KERNEL);
if (!os2name)
return -ENOMEM;
strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);
name = os2name;
namelen -= XATTR_OS2_PREFIX_LEN;
}
xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) {
rc = xattr_size;
......@@ -714,10 +792,13 @@ int __jfs_setxattr(struct inode *inode, const char *name, void *value,
release:
ea_release(inode, &ea_buf);
out:
if (os2name)
kfree(os2name);
return rc;
}
int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t value_len, int flags)
{
if (value == NULL) { /* empty EA, do not remove */
......@@ -728,7 +809,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
}
static int can_get_xattr(struct inode *inode, const char *name)
static inline int can_get_xattr(struct inode *inode, const char *name)
{
return permission(inode, MAY_READ);
}
......@@ -742,12 +823,23 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
int xattr_size;
ssize_t size;
int namelen = strlen(name);
char *os2name = NULL;
int rc;
char *value;
if ((rc = can_get_xattr(inode, name)))
return rc;
if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
GFP_KERNEL);
if (!os2name)
return -ENOMEM;
strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);
name = os2name;
namelen -= XATTR_OS2_PREFIX_LEN;
}
xattr_size = ea_get(inode, &ea_buf, 0);
if (xattr_size < 0) {
size = xattr_size;
......@@ -780,6 +872,8 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
release:
ea_release(inode, &ea_buf);
out:
if (os2name)
kfree(os2name);
return size;
}
......@@ -813,7 +907,7 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
/* compute required size of list */
for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea))
size += ea->namelen + 1;
size += name_size(ea) + 1;
if (!data)
goto release;
......@@ -826,9 +920,8 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
/* Copy attribute names to buffer */
buffer = data;
for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) {
memcpy(buffer, ea->name, ea->namelen);
buffer[ea->namelen] = 0;
buffer += ea->namelen + 1;
int namelen = copy_name(buffer, ea);
buffer += namelen + 1;
}
release:
......
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