~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/xfs_xattr.c

Version: ~ [ linux-5.8-rc5 ] ~ [ linux-5.7.8 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.51 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.132 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.188 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.230 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.230 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (C) 2008 Christoph Hellwig.
  3  * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
  4  *
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License as
  7  * published by the Free Software Foundation.
  8  *
  9  * This program is distributed in the hope that it would be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, write the Free Software Foundation,
 16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17  */
 18 
 19 #include "xfs.h"
 20 #include "xfs_format.h"
 21 #include "xfs_log_format.h"
 22 #include "xfs_trans_resv.h"
 23 #include "xfs_sb.h"
 24 #include "xfs_ag.h"
 25 #include "xfs_mount.h"
 26 #include "xfs_da_format.h"
 27 #include "xfs_inode.h"
 28 #include "xfs_attr.h"
 29 #include "xfs_attr_leaf.h"
 30 #include "xfs_acl.h"
 31 
 32 #include <linux/posix_acl_xattr.h>
 33 #include <linux/xattr.h>
 34 
 35 
 36 static int
 37 xfs_xattr_get(struct dentry *dentry, const char *name,
 38                 void *value, size_t size, int xflags)
 39 {
 40         struct xfs_inode *ip = XFS_I(dentry->d_inode);
 41         int error, asize = size;
 42 
 43         if (strcmp(name, "") == 0)
 44                 return -EINVAL;
 45 
 46         /* Convert Linux syscall to XFS internal ATTR flags */
 47         if (!size) {
 48                 xflags |= ATTR_KERNOVAL;
 49                 value = NULL;
 50         }
 51 
 52         error = xfs_attr_get(ip, (unsigned char *)name, value, &asize, xflags);
 53         if (error)
 54                 return error;
 55         return asize;
 56 }
 57 
 58 static int
 59 xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
 60                 size_t size, int flags, int xflags)
 61 {
 62         struct xfs_inode *ip = XFS_I(dentry->d_inode);
 63 
 64         if (strcmp(name, "") == 0)
 65                 return -EINVAL;
 66 
 67         /* Convert Linux syscall to XFS internal ATTR flags */
 68         if (flags & XATTR_CREATE)
 69                 xflags |= ATTR_CREATE;
 70         if (flags & XATTR_REPLACE)
 71                 xflags |= ATTR_REPLACE;
 72 
 73         if (!value)
 74                 return xfs_attr_remove(ip, (unsigned char *)name, xflags);
 75         return xfs_attr_set(ip, (unsigned char *)name,
 76                                 (void *)value, size, xflags);
 77 }
 78 
 79 static const struct xattr_handler xfs_xattr_user_handler = {
 80         .prefix = XATTR_USER_PREFIX,
 81         .flags  = 0, /* no flags implies user namespace */
 82         .get    = xfs_xattr_get,
 83         .set    = xfs_xattr_set,
 84 };
 85 
 86 static const struct xattr_handler xfs_xattr_trusted_handler = {
 87         .prefix = XATTR_TRUSTED_PREFIX,
 88         .flags  = ATTR_ROOT,
 89         .get    = xfs_xattr_get,
 90         .set    = xfs_xattr_set,
 91 };
 92 
 93 static const struct xattr_handler xfs_xattr_security_handler = {
 94         .prefix = XATTR_SECURITY_PREFIX,
 95         .flags  = ATTR_SECURE,
 96         .get    = xfs_xattr_get,
 97         .set    = xfs_xattr_set,
 98 };
 99 
100 const struct xattr_handler *xfs_xattr_handlers[] = {
101         &xfs_xattr_user_handler,
102         &xfs_xattr_trusted_handler,
103         &xfs_xattr_security_handler,
104 #ifdef CONFIG_XFS_POSIX_ACL
105         &posix_acl_access_xattr_handler,
106         &posix_acl_default_xattr_handler,
107 #endif
108         NULL
109 };
110 
111 static unsigned int xfs_xattr_prefix_len(int flags)
112 {
113         if (flags & XFS_ATTR_SECURE)
114                 return sizeof("security");
115         else if (flags & XFS_ATTR_ROOT)
116                 return sizeof("trusted");
117         else
118                 return sizeof("user");
119 }
120 
121 static const char *xfs_xattr_prefix(int flags)
122 {
123         if (flags & XFS_ATTR_SECURE)
124                 return xfs_xattr_security_handler.prefix;
125         else if (flags & XFS_ATTR_ROOT)
126                 return xfs_xattr_trusted_handler.prefix;
127         else
128                 return xfs_xattr_user_handler.prefix;
129 }
130 
131 static int
132 xfs_xattr_put_listent(
133         struct xfs_attr_list_context *context,
134         int             flags,
135         unsigned char   *name,
136         int             namelen,
137         int             valuelen,
138         unsigned char   *value)
139 {
140         unsigned int prefix_len = xfs_xattr_prefix_len(flags);
141         char *offset;
142         int arraytop;
143 
144         ASSERT(context->count >= 0);
145 
146         /*
147          * Only show root namespace entries if we are actually allowed to
148          * see them.
149          */
150         if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN))
151                 return 0;
152 
153         arraytop = context->count + prefix_len + namelen + 1;
154         if (arraytop > context->firstu) {
155                 context->count = -1;    /* insufficient space */
156                 return 1;
157         }
158         offset = (char *)context->alist + context->count;
159         strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
160         offset += prefix_len;
161         strncpy(offset, (char *)name, namelen);                 /* real name */
162         offset += namelen;
163         *offset = '\0';
164         context->count += prefix_len + namelen + 1;
165         return 0;
166 }
167 
168 static int
169 xfs_xattr_put_listent_sizes(
170         struct xfs_attr_list_context *context,
171         int             flags,
172         unsigned char   *name,
173         int             namelen,
174         int             valuelen,
175         unsigned char   *value)
176 {
177         context->count += xfs_xattr_prefix_len(flags) + namelen + 1;
178         return 0;
179 }
180 
181 static int
182 list_one_attr(const char *name, const size_t len, void *data,
183                 size_t size, ssize_t *result)
184 {
185         char *p = data + *result;
186 
187         *result += len;
188         if (!size)
189                 return 0;
190         if (*result > size)
191                 return -ERANGE;
192 
193         strcpy(p, name);
194         return 0;
195 }
196 
197 ssize_t
198 xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
199 {
200         struct xfs_attr_list_context context;
201         struct attrlist_cursor_kern cursor = { 0 };
202         struct inode            *inode = dentry->d_inode;
203         int                     error;
204 
205         /*
206          * First read the regular on-disk attributes.
207          */
208         memset(&context, 0, sizeof(context));
209         context.dp = XFS_I(inode);
210         context.cursor = &cursor;
211         context.resynch = 1;
212         context.alist = data;
213         context.bufsize = size;
214         context.firstu = context.bufsize;
215 
216         if (size)
217                 context.put_listent = xfs_xattr_put_listent;
218         else
219                 context.put_listent = xfs_xattr_put_listent_sizes;
220 
221         xfs_attr_list_int(&context);
222         if (context.count < 0)
223                 return -ERANGE;
224 
225         /*
226          * Then add the two synthetic ACL attributes.
227          */
228         if (posix_acl_access_exists(inode)) {
229                 error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
230                                 strlen(POSIX_ACL_XATTR_ACCESS) + 1,
231                                 data, size, &context.count);
232                 if (error)
233                         return error;
234         }
235 
236         if (posix_acl_default_exists(inode)) {
237                 error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
238                                 strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
239                                 data, size, &context.count);
240                 if (error)
241                         return error;
242         }
243 
244         return context.count;
245 }
246 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp