Hottest Free Downloads - DownloadPipe.com Over 197,000 downloads! Bookmark Now!
DownloadPipe.com - New Downloads Every Minute
 SEARCH:
FAQFAQ    SearchSearch      ProfileProfile    Private MessagesPrivate Messages   Log inLog in

[PATCH 1/2] vfs: new open(2) flag to open filesystem node

 
   Linux (Home) -> Kernel RSS
Next:  igotU mini GPS datalogger (navman/non-standard us..  
Author Message
David Howells

External


Since: Aug 04, 2005
Posts: 74



(Msg. 1) Posted: Fri Jul 03, 2009 3:26 pm
Post subject: [PATCH 1/2] vfs: new open(2) flag to open filesystem node
Archived from groups: linux>kernel (more info?)

From: Miklos Szeredi <miklos.TakeThisOut@szeredi.hu>

This patch adds a new open flag, O_NODE. This flag means: open just
the filesystem node instead of the object referenced by the node.

Opening a file will not call the driver's ->open() method and will not
have any side effect other than referencing the dentry/vfsmount from
the struct file pointer.

Currently O_NODE can only be used together with O_NOACCESS (value 3),
meaning that read(2) and write(2) will return EBADF and no permission
is necessary to open the file. This is logical for device nodes and
fifos. For directories we could allow O_RDONLY, and for regular files
any access mode, but this is not done yet.

O_NODE used together with O_NOFOLLOW will open a symlink node itself
instead of returning ELOOP. O_NOFOLLOW will not prevent following
mountpoints if used together with O_NODE. In theory we could allow
O_RDONLY for symlinks too and return the contents of the link on
read(2).

Filesystems which want to install special file operations for O_NODE
opens (e.g. ioctl) may set S_OPEN_NODE flag in the inode. This will
cause dentry_open() to call inode->i_fop->open, and the filesystem is
responsible for handling the O_NODE flag and installing the right
filesystem operations in file->f_op.

Signed-off-by: Miklos Szeredi <mszeredi.TakeThisOut@suse.cz>
Acked-by: David Howells <dhowells.TakeThisOut@redhat.com>
---

fs/file_table.c | 6 +++-
fs/locks.c | 3 ++
fs/namei.c | 65 ++++++++++++++++++++++++++-----------------
fs/open.c | 12 +++++++-
include/asm-generic/fcntl.h | 4 +++
include/linux/fs.h | 1 +
6 files changed, 62 insertions(+), 29 deletions(-)


diff --git a/fs/file_table.c b/fs/file_table.c
index 334ce39..2f40336 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -281,8 +281,10 @@ void __fput(struct file *file)
file->f_op->release(inode, file);
security_file_free(file);
ima_file_free(file);
- if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
- cdev_put(inode->i_cdev);
+ if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) {
+ if (!(file->f_flags & O_NODE))
+ cdev_put(inode->i_cdev);
+ }
fops_put(file->f_op);
put_pid(file->f_owner.pid);
file_kill(file);
diff --git a/fs/locks.c b/fs/locks.c
index b6440f5..8ab6e84 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1183,6 +1183,9 @@ int __break_lease(struct inode *inode, unsigned int mode)
unsigned long break_time;
int i_have_this_lease = 0;

+ if (!(mode & (FMODE_READ | FMODE_WRITE)))
+ return 0;
+
new_fl = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK);

lock_kernel();
diff --git a/fs/namei.c b/fs/namei.c
index f3c5b27..c1d9f58 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1160,7 +1160,9 @@ static int path_lookup_open(int dfd, const char *name,
nd->intent.open.file = filp;
nd->intent.open.flags = open_flags;
nd->intent.open.create_mode = 0;
- err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
+ if (!(open_flags & O_NODE))
+ lookup_flags |= LOOKUP_OPEN;
+ err = do_path_lookup(dfd, name, lookup_flags, nd);
if (IS_ERR(nd->intent.open.file)) {
if (err == 0) {
err = PTR_ERR(nd->intent.open.file);
@@ -1511,22 +1513,27 @@ int may_open(struct path *path, int acc_mode, int flag)
if (!inode)
return -ENOENT;

- switch (inode->i_mode & S_IFMT) {
- case S_IFLNK:
- return -ELOOP;
- case S_IFDIR:
- if (acc_mode & MAY_WRITE)
- return -EISDIR;
- break;
- case S_IFBLK:
- case S_IFCHR:
- if (path->mnt->mnt_flags & MNT_NODEV)
+ if ((flag & O_NODE)) {
+ if (acc_mode & (MAY_READ | MAY_WRITE))
return -EACCES;
- /*FALLTHRU*/
- case S_IFIFO:
- case S_IFSOCK:
- flag &= ~O_TRUNC;
- break;
+ } else {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFLNK:
+ return -ELOOP;
+ case S_IFDIR:
+ if (acc_mode & MAY_WRITE)
+ return -EISDIR;
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ if (path->mnt->mnt_flags & MNT_NODEV)
+ return -EACCES;
+ /*FALLTHRU*/
+ case S_IFIFO:
+ case S_IFSOCK:
+ flag &= ~O_TRUNC;
+ break;
+ }
}

error = inode_permission(inode, acc_mode);
@@ -1629,14 +1636,16 @@ out_unlock:
* 11 - read-write
* for the internal routines (ie open_namei()/follow_link() etc)
* This is more logical, and also allows the 00 "no perm needed"
- * to be used for symlinks (where the permissions are checked
- * later).
+ * to be used for opening a symlink, pipe, socket or device with
+ * O_NODE.
*
*/
static inline int open_to_namei_flags(int flag)
{
if ((flag+1) & O_ACCMODE)
flag++;
+ else if (flag & O_NODE)
+ flag &= ~O_ACCMODE;
return flag;
}

@@ -1724,7 +1733,9 @@ struct file *do_filp_open(int dfd, const char *pathname,
nd.intent.open.create_mode = mode;
dir = nd.path.dentry;
nd.flags &= ~LOOKUP_PARENT;
- nd.flags |= LOOKUP_CREATE | LOOKUP_OPEN;
+ nd.flags |= LOOKUP_CREATE;
+ if (!(open_flag & O_NODE))
+ nd.flags |= LOOKUP_OPEN;
if (flag & O_EXCL)
nd.flags |= LOOKUP_EXCL;
mutex_lock(&dir->d_inode->i_mutex);
@@ -1783,19 +1794,24 @@ do_last:

if (__follow_mount(&path)) {
error = -ELOOP;
- if (flag & O_NOFOLLOW)
+ if ((flag & O_NOFOLLOW) & !(flag & O_NODE))
goto exit_dput;
}

error = -ENOENT;
if (!path.dentry->d_inode)
goto exit_dput;
- if (path.dentry->d_inode->i_op->follow_link)
- goto do_link;
+ if (path.dentry->d_inode->i_op->follow_link) {
+ if (!(flag & O_NOFOLLOW))
+ goto do_link;
+ error = -ELOOP;
+ if (!(flag & O_NODE))
+ goto exit_dput;
+ }

path_to_nameidata(&path, &nd);
error = -EISDIR;
- if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
+ if (S_ISDIR(path.dentry->d_inode->i_mode))
goto exit;
ok:
/*
@@ -1849,9 +1865,6 @@ exit_parent:
return ERR_PTR(error);

do_link:
- error = -ELOOP;
- if (flag & O_NOFOLLOW)
- goto exit_dput;
/*
* This is subtle. Instead of calling do_follow_link() we do the
* thing by hands. The reason is that this way we have zero link_count
diff --git a/fs/open.c b/fs/open.c
index b1284bc..b9b7be8 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -805,12 +805,17 @@ static inline int __get_file_write_access(struct inode *inode,
return error;
}

+static const struct file_operations default_node_fops = {
+ .llseek = no_llseek,
+};
+
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
int flags, struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
struct inode *inode;
+ const struct file_operations *fops;
int error;

f->f_flags = flags;
@@ -829,7 +834,12 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f->f_path.dentry = dentry;
f->f_path.mnt = mnt;
f->f_pos = 0;
- f->f_op = fops_get(inode->i_fop);
+
+ fops = inode->i_fop;
+ if ((flags & O_NODE) && !(inode->i_flags & S_OPEN_NODE))
+ fops = &default_node_fops;
+ f->f_op = fops_get(fops);
+
file_move(f, &inode->i_sb->s_files);

error = security_dentry_open(f, cred);
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index 4d3e483..3cbd9b1 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -9,6 +9,7 @@
#define O_RDONLY 00000000
#define O_WRONLY 00000001
#define O_RDWR 00000002
+#define O_NOACCESS 00000003
#ifndef O_CREAT
#define O_CREAT 00000100 /* not fcntl */
#endif
@@ -51,6 +52,9 @@
#ifndef O_CLOEXEC
#define O_CLOEXEC 02000000 /* set close_on_exec */
#endif
+#ifndef O_NODE
+#define O_NODE 04000000 /* open filesystem node, not device */
+#endif
#ifndef O_NDELAY
#define O_NDELAY O_NONBLOCK
#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0a20392..22d344c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -231,6 +231,7 @@ struct inodes_stat_t {
#define S_NOCMTIME 128 /* Do not update file c/mtime */
#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */
#define S_PRIVATE 512 /* Inode is fs-internal */
+#define S_OPEN_NODE 1024 /* Fs is prepared for O_NODE opens */

/*
* Note that nosuid etc flags are inode-specific: setting some file-system

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo.TakeThisOut@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Back to top
Login to vote
David Howells

External


Since: Aug 04, 2005
Posts: 74



(Msg. 2) Posted: Fri Jul 03, 2009 3:26 pm
Post subject: [PATCH 2/2] AFS: Export some AFS-specific information through xattrs [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

Export some AFS-specific information through xattrs with an "afs." prefix.
This allows some pioctls to be emulated in userspace.

This can be tested directly using the getfattr program:

[root@andromeda ~]# getfattr -d -m - /afs
getfattr: Removing leading '/' from absolute path names
# file: afs
security.selinux="system_u:object_r:nfs_t:s0\000"
system.afs.cell="procyon.org.uk"
system.afs.fid="20000000:00000001:00000001"

A tentative wrapper for partially implementing pioctl in userspace could look
like (this implementation is designed for LD_PRELOAD overloading of syscall()
for simplicity, but should be linked in properly):

/* Userspace version of pioctl
*
* Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define syscall _X_syscall
#include <unistd.h>
#undef syscall
#include <syscall.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/xattr.h>
#include <errno.h>
#include <dlfcn.h>
#define RTLD_NEXT ((void *) -1l)

#define O_NOACCESS 00000003
#define O_NOFOLLOW 00400000 /* don't follow links */
#define O_NODE 04000000 /* open filesystem node, not device */

struct ViceIoctl {
caddr_t in;
caddr_t out;
short in_size;
short out_size;
};

#define _VICEIOCTL(nr) _IOW('V', nr, struct ViceIoctl)
#define _CVICEIOCTL(nr) _IOW('C', nr, struct ViceIoctl)
#define _OVICEIOCTL(nr) _IOW('O', nr, struct ViceIoctl)

#define AFS_PIOCTL 0x14
#define VIOCGETFID _VICEIOCTL(22) /* get file ID */

#define AFS_XATTR_PREFIX "system.afs."

struct afs_fid {
unsigned vid; /* volume ID */
unsigned vnode; /* file index within volume */
unsigned unique; /* unique ID number (file index version) */
};

static long (*libc_syscall)(int number, long a, long b, long c, long d, long e, long f);

/*
* VIOCGETFID
*/
static int afs_viocgetfid(int fd, int cmd, struct ViceIoctl *args)
{
struct afs_fid *fid = (void *) args->out;
char buf[8*3];
int ret;

if (args->out_size < sizeof(struct afs_fid) || !args->out) {
errno = EINVAL;
return -1;
}

ret = fgetxattr(fd, AFS_XATTR_PREFIX "fid", buf, sizeof(buf) - 1);
if (ret == -1)
return ret;

buf[23] = 0;
if (sscanf(buf, "%x:%x:%x", &fid->vid, &fid->vnode, &fid->unique) != 3) {
errno = EIO;
return -1;
}

args->out_size = sizeof(struct afs_fid);
return 0;
}

/*
* the main pioctl switch
*/
static long pioctl(const char *path, int cmd, struct ViceIoctl *args,
int follow)
{
long ret;
int fd, ret2;

printf("pioctl(%s,%x,%p,%d)\n", path, _IOC_NR(cmd), args, follow);

if (args->in_size < 0 || args->out_size < 0)
goto invalid_arg;

/* handle pathless pioctls */
switch (cmd) {
default:
if (!path) {
errno = EINVAL;
return -1;
}
break;
}

fd = open(path, O_NODE | O_NOACCESS | (follow ? 0 : O_NOFOLLOW), 0);
if (fd == -1)
return -1;

switch (cmd) {
case VIOCGETFID:
ret = afs_viocgetfid(fd, cmd, args);
break;
default:
errno = EOPNOTSUPP;
ret = -1;
break;
}

ret2 = close(fd);
if (ret != -1 && ret2 == -1)
ret = ret2;
return ret;

invalid_arg:
errno = EINVAL;
return -1;
}

static long afs(long function, long b, long c, long d, long e, long f)
{
if (function == AFS_PIOCTL) {
return pioctl((const char *) b,
(int) c,
(struct ViceIoctl *) d,
(int) e);
} else {
printf("afs(%ld,%lx)\n", function, b);
errno = ENOSYS;
return -1;
}
}

long syscall(int number, long a, long b, long c, long d, long e, long f)
{
long ret;

if (!libc_syscall) {
libc_syscall = dlsym(RTLD_NEXT, "syscall");
if (!libc_syscall) {
fprintf(stderr, "Cannot get syscall\n");
abort();
}
}

ret = libc_syscall(number, a, b, c, d, e, f);
if (ret != -1)
return ret;

if (errno == ENOSYS && number == SYS_afs_syscall)
return afs(a, b, c, d, e, f);

return -1;
}

This can be tested like this:

gcc -gstabs+ -fpic -Wall -c -o pioctl.o pioctl.c
gcc -shared -o libpioctl.so pioctl.o -ldl -lc
[root@andromeda ~]# LD_PRELOAD=/tmp/libpioctl.so fs getfid /afs
pioctl(/afs,16,0x7fffdadc6560,1)
File /afs (1.0.0) contained in volume 1

Signed-off-by: David Howells <dhowells RemoveThis @redhat.com>
---

fs/afs/Makefile | 3 +
fs/afs/dir.c | 2 +
fs/afs/file.c | 2 +
fs/afs/inode.c | 8 +++
fs/afs/internal.h | 5 ++
fs/afs/mntpt.c | 2 +
fs/afs/security.c | 18 ++++--
fs/afs/xattr.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++
security/security.c | 1
9 files changed, 197 insertions(+), 6 deletions(-)
create mode 100644 fs/afs/xattr.c


diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 4f64b95..095c541 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -27,6 +27,7 @@ kafs-objs := \
vlocation.o \
vnode.o \
volume.o \
- write.o
+ write.o \
+ xattr.o

obj-$(CONFIG_AFS_FS) := kafs.o
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 9bd7577..5272872 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -60,6 +60,8 @@ const struct inode_operations afs_dir_inode_operations = {
.permission = afs_permission,
.getattr = afs_getattr,
.setattr = afs_setattr,
+ .getxattr = afs_getxattr,
+ .listxattr = afs_listxattr,
};

static const struct dentry_operations afs_fs_dentry_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 0149dab..1586496 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -45,6 +45,8 @@ const struct inode_operations afs_file_inode_operations = {
.getattr = afs_getattr,
.setattr = afs_setattr,
.permission = afs_permission,
+ .getxattr = afs_getxattr,
+ .listxattr = afs_listxattr,
};

const struct address_space_operations afs_fs_aops = {
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index c048f06..8fe6192 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -27,6 +27,14 @@ struct afs_iget_data {
struct afs_volume *volume; /* volume on which resides */
};

+const struct inode_operations afs_symlink_inode_operations = {
+ .readlink = generic_readlink,
+ .follow_link = page_follow_link_light,
+ .put_link = page_put_link,
+ .getxattr = afs_getxattr,
+ .listxattr = afs_listxattr,
+};
+
/*
* map the AFS file status to the inode member variables
*/
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 59049b0..5a815e8 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -741,6 +741,11 @@ extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
extern int afs_writeback_all(struct afs_vnode *);
extern int afs_fsync(struct file *, struct dentry *, int);

+/*
+ * xattr.c
+ */
+extern ssize_t afs_listxattr(struct dentry *, char *, size_t);
+extern ssize_t afs_getxattr(struct dentry *, const char *, void *, size_t);

/*****************************************************************************/
/*
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index c52be53..994f75d 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -37,6 +37,8 @@ const struct inode_operations afs_mntpt_inode_operations = {
.follow_link = afs_mntpt_follow_link,
.readlink = page_readlink,
.getattr = afs_getattr,
+ .getxattr = afs_getxattr,
+ .listxattr = afs_listxattr,
};

static LIST_HEAD(afs_vfsmounts);
diff --git a/fs/afs/security.c b/fs/afs/security.c
index 3ef5043..6c9e011 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -291,7 +291,7 @@ int afs_permission(struct inode *inode, int mask)
struct key *key;
int ret;

- _enter("{{%x:%u},%lx},%x,",
+ kenter("{{%x:%u},%lx},%x,",
vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask);

key = afs_request_key(vnode->volume->cell);
@@ -315,7 +315,7 @@ int afs_permission(struct inode *inode, int mask)
goto error;

/* interpret the access mask */
- _debug("REQ %x ACC %x on %s",
+ kdebug("REQ %x ACC %x on %s",
mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file");

if (S_ISDIR(inode->i_mode)) {
@@ -330,8 +330,11 @@ int afs_permission(struct inode *inode, int mask)
AFS_ACE_INSERT | /* create, mkdir, symlink, rename to */
AFS_ACE_WRITE))) /* chmod */
goto permission_denied;
+ } else if (mask & MAY_OPEN) {
} else {
- BUG();
+ printk(KERN_WARNING "AFS: Unhandled perm mask %x\n",
+ mask);
+ goto permission_denied;
}
} else {
if (!(access & AFS_ACE_LOOKUP))
@@ -342,18 +345,23 @@ int afs_permission(struct inode *inode, int mask)
} else if (mask & MAY_WRITE) {
if (!(access & AFS_ACE_WRITE))
goto permission_denied;
+ } else if (mask & MAY_OPEN) {
+ } else {
+ printk(KERN_WARNING "AFS: Unhandled perm mask %x\n",
+ mask);
+ goto permission_denied;
}
}

key_put(key);
ret = generic_permission(inode, mask, NULL);
- _leave(" = %d", ret);
+ kleave(" = %d", ret);
return ret;

permission_denied:
ret = -EACCES;
error:
key_put(key);
- _leave(" = %d", ret);
+ kleave(" = %d [error]", ret);
return ret;
}
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
new file mode 100644
index 0000000..6e9d832
--- /dev/null
+++ b/fs/afs/xattr.c
@@ -0,0 +1,162 @@
+/* AFS extended attribute support
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include "internal.h"
+
+static const char afs_xattr_prefix[] = XATTR_SYSTEM_PREFIX "afs.";
+
+typedef ssize_t (*afs_xattr_get_t)(struct afs_vnode *vnode, struct key *key,
+ void *value, size_t size);
+
+struct afs_xattr {
+ const char *name;
+ afs_xattr_get_t get;
+};
+
+/*
+ * Get the AFS file identifier of a file
+ */
+static ssize_t afs_xattr_get_fid(struct afs_vnode *vnode, struct key *key,
+ void *value, size_t size)
+{
+ ssize_t ret;
+
+ _enter("");
+
+ ret = snprintf(value, size, "%08x:%08x:%08x",
+ vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
+
+ _leave(" = %zd", ret);
+ return ret;
+}
+
+/*
+ * Get the AFS cell name of a file
+ */
+static ssize_t afs_xattr_get_cell(struct afs_vnode *vnode, struct key *key,
+ void *value, size_t size)
+{
+ ssize_t ret;
+
+ _enter("");
+
+ ret = snprintf(value, size, "%s", vnode->volume->vlocation->cell->name);
+
+ _leave(" = %zd", ret);
+ return ret;
+}
+
+/*
+ * ordered list of AFS attributes
+ */
+static const struct afs_xattr afs_xattrs[] = {
+ { "cell", afs_xattr_get_cell },
+ { "fid", afs_xattr_get_fid },
+ { NULL }
+};
+
+/*
+ * list extended attributes for an AFS file
+ */
+ssize_t afs_listxattr(struct dentry *dentry, char *list, size_t size)
+{
+ const struct afs_xattr *p;
+ struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+ struct key *key;
+ ssize_t total, nlen, len, plen, ret;
+ char *to = list;
+
+ _enter(",%p,%zu", list, size);
+
+ key = afs_request_key(vnode->volume->cell);
+ if (IS_ERR(key)) {
+ ret = PTR_ERR(key);
+ _leave(" = %ld [no key]", ret);
+ return ret;
+ }
+
+ /* list the AFS attributes */
+ _debug("afs attr");
+ plen = sizeof(afs_xattr_prefix);
+ total = 0;
+ for (p = afs_xattrs; p->name; p++) {
+ nlen = strlen(p->name);
+ len = nlen + sizeof(afs_xattr_prefix);
+ total += len;
+ if (len <= size && list) {
+ size -= len;
+ memcpy(to, afs_xattr_prefix, plen - 1);
+ to += plen - 1;
+ memcpy(to, p->name, nlen + 1);
+ to += nlen + 1;
+ }
+ }
+
+ /* TODO: tag on user attributes when they become available */
+ _debug("user attr");
+
+ /* tag on the security subsys's attributes */
+ _debug("sec attr");
+ len = security_inode_listsecurity(dentry->d_inode, to, size);
+ if (IS_ERR_VALUE(len))
+ total = len;
+ else
+ total += len;
+
+ key_put(key);
+ _leave(" = %zd [%zd]", total, to - list);
+ return total;
+}
+
+/*
+ * get extended attributes for an AFS file
+ */
+ssize_t afs_getxattr(struct dentry *dentry, const char *name,
+ void *value, size_t size)
+{
+ const struct afs_xattr *p;
+ struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+ struct key *key;
+ ssize_t ret;
+
+ _enter(",%s,,%zu", name, size);
+
+ key = afs_request_key(vnode->volume->cell);
+ if (IS_ERR(key)) {
+ ret = PTR_ERR(key);
+ _leave(" = %ld [no key]", ret);
+ return ret;
+ }
+
+ /* get AFS attributes */
+ if (memcmp(name, afs_xattr_prefix, sizeof(afs_xattr_prefix) - 1) == 0) {
+ name += sizeof(afs_xattr_prefix) - 1;
+
+ for (p = afs_xattrs; p->name; p++) {
+ if (strcmp(name, p->name) == 0) {
+ ret = p->get(vnode, key, value, size);
+ goto out;
+ }
+ }
+ goto noattr;
+ }
+
+ /* TODO: get user attributes when they become available */
+
+noattr:
+ ret = -ENODATA;
+out:
+ key_put(key);
+ _leave(" = %zd", ret);
+ return ret;
+}
diff --git a/security/security.c b/security/security.c
index dc7674f..fe6b812 100644
--- a/security/security.c
+++ b/security/security.c
@@ -609,6 +609,7 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
return 0;
return security_ops->inode_listsecurity(inode, buffer, buffer_size);
}
+EXPORT_SYMBOL(security_inode_listsecurity);

void security_inode_getsecid(const struct inode *inode, u32 *secid)
{

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo RemoveThis @vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Back to top
Login to vote
Display posts from previous:   
Related Topics:
[patch] mm: Patch to convert global dirty_exceeded flag to.. - Patch to convert global dirty_exceeded flag to per-node node_dirty_exceeded. dirty_exceeded ping pongs between nodes in order to force all cpus in the system to increase the frequency of calls to balance_dirty_pages. Currently dirty_exceeded is used by...

[PATCH] fix cdrom open - Hi Jens, Some time ago the cdrom open routine was changed so that we call the driver's open routine before checking to see if it is read only. However, if we discovered that a read write open was not possible and the open flags required a writable open...

[PATCH] open: O_DIRECTORY and O_CREAT together should fail - Add a check for O_DIRECTORY in the O_CREAT path, and return -EINVAL. Current behavior is inconsistent with documentation: open(..., O_DIRECTORY|O_CREAT) succeeds if file didn't exist, and returned descriptor does not refer to a directory. No other..

[PATCH] dequeue a huge page near to this node - The following patch changes the dequeueing to select a huge page near the node executing instead of always beginning to check for free nodes from node 0. This will result in a placement of the huge pages near the executing processor improving..

[PATCH] Register sysfs file for hotpluged new node - Hello. This is the last part of patches for new nodes addition v4. It is to create sysfs file for new node. It adds arch specific functions 'arch_register_node()' and 'arch_unregister_node()' to call the generic function 'register_node()' and..
       Linux (Home) -> Kernel All times are: Pacific Time (US & Canada) (change)
Page 1 of 1

 
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Categories:
 Windows Forums
 Game Forums
  Linux Forums
 Mac Forums
 PDA Forums
 Mobile Forums
  Top  |  Store  |  RSS Feeds RSS  |  Data Feeds  |  Advertise  |  Submit  |  Bookmark  |  Newsletter  |  Contact