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

TOMOYO Linux Cross Reference
Linux/fs/xattr.c

Version: ~ [ linux-5.9-rc6 ] ~ [ linux-5.8.10 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.66 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.146 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.198 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.236 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.236 ] ~ [ 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   File: fs/xattr.c
  3 
  4   Extended attribute handling.
  5 
  6   Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
  7   Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
  8  */
  9 #include <linux/fs.h>
 10 #include <linux/slab.h>
 11 #include <linux/smp_lock.h>
 12 #include <linux/file.h>
 13 #include <linux/xattr.h>
 14 #include <linux/namei.h>
 15 #include <linux/security.h>
 16 #include <asm/uaccess.h>
 17 
 18 /*
 19  * Extended attribute memory allocation wrappers, originally
 20  * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
 21  * Values larger than a page are uncommon - extended attributes
 22  * are supposed to be small chunks of metadata, and it is quite
 23  * unusual to have very many extended attributes, so lists tend
 24  * to be quite short as well.  The 64K upper limit is derived
 25  * from the extended attribute size limit used by XFS.
 26  * Intentionally allow zero @size for value/list size requests.
 27  */
 28 static void *
 29 xattr_alloc(size_t size, size_t limit)
 30 {
 31         void *ptr;
 32 
 33         if (size > limit)
 34                 return ERR_PTR(-E2BIG);
 35 
 36         if (!size)      /* size request, no buffer is needed */
 37                 return NULL;
 38 
 39         ptr = kmalloc((unsigned long) size, GFP_KERNEL);
 40         if (!ptr)
 41                 return ERR_PTR(-ENOMEM);
 42         return ptr;
 43 }
 44 
 45 static void
 46 xattr_free(void *ptr, size_t size)
 47 {
 48         if (size)       /* for a size request, no buffer was needed */
 49                 kfree(ptr);
 50 }
 51 
 52 /*
 53  * Extended attribute SET operations
 54  */
 55 static long
 56 setxattr(struct dentry *d, char __user *name, void __user *value,
 57          size_t size, int flags)
 58 {
 59         int error;
 60         void *kvalue;
 61         char kname[XATTR_NAME_MAX + 1];
 62 
 63         if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
 64                 return -EINVAL;
 65 
 66         error = strncpy_from_user(kname, name, sizeof(kname));
 67         if (error == 0 || error == sizeof(kname))
 68                 error = -ERANGE;
 69         if (error < 0)
 70                 return error;
 71 
 72         kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
 73         if (IS_ERR(kvalue))
 74                 return PTR_ERR(kvalue);
 75 
 76         if (size > 0 && copy_from_user(kvalue, value, size)) {
 77                 xattr_free(kvalue, size);
 78                 return -EFAULT;
 79         }
 80 
 81         error = -EOPNOTSUPP;
 82         if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
 83                 down(&d->d_inode->i_sem);
 84                 error = security_inode_setxattr(d, kname, kvalue, size, flags);
 85                 if (error)
 86                         goto out;
 87                 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
 88                 if (!error)
 89                         security_inode_post_setxattr(d, kname, kvalue, size, flags);
 90 out:
 91                 up(&d->d_inode->i_sem);
 92         }
 93         xattr_free(kvalue, size);
 94         return error;
 95 }
 96 
 97 asmlinkage long
 98 sys_setxattr(char __user *path, char __user *name, void __user *value,
 99              size_t size, int flags)
100 {
101         struct nameidata nd;
102         int error;
103 
104         error = user_path_walk(path, &nd);
105         if (error)
106                 return error;
107         error = setxattr(nd.dentry, name, value, size, flags);
108         path_release(&nd);
109         return error;
110 }
111 
112 asmlinkage long
113 sys_lsetxattr(char __user *path, char __user *name, void __user *value,
114               size_t size, int flags)
115 {
116         struct nameidata nd;
117         int error;
118 
119         error = user_path_walk_link(path, &nd);
120         if (error)
121                 return error;
122         error = setxattr(nd.dentry, name, value, size, flags);
123         path_release(&nd);
124         return error;
125 }
126 
127 asmlinkage long
128 sys_fsetxattr(int fd, char __user *name, void __user *value,
129               size_t size, int flags)
130 {
131         struct file *f;
132         int error = -EBADF;
133 
134         f = fget(fd);
135         if (!f)
136                 return error;
137         error = setxattr(f->f_dentry, name, value, size, flags);
138         fput(f);
139         return error;
140 }
141 
142 /*
143  * Extended attribute GET operations
144  */
145 static ssize_t
146 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
147 {
148         ssize_t error;
149         void *kvalue;
150         char kname[XATTR_NAME_MAX + 1];
151 
152         error = strncpy_from_user(kname, name, sizeof(kname));
153         if (error == 0 || error == sizeof(kname))
154                 error = -ERANGE;
155         if (error < 0)
156                 return error;
157 
158         kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
159         if (IS_ERR(kvalue))
160                 return PTR_ERR(kvalue);
161 
162         error = -EOPNOTSUPP;
163         if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
164                 error = security_inode_getxattr(d, kname);
165                 if (error)
166                         goto out;
167                 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
168         }
169 
170         if (kvalue && error > 0)
171                 if (copy_to_user(value, kvalue, error))
172                         error = -EFAULT;
173 out:
174         xattr_free(kvalue, size);
175         return error;
176 }
177 
178 asmlinkage ssize_t
179 sys_getxattr(char __user *path, char __user *name, void __user *value,
180              size_t size)
181 {
182         struct nameidata nd;
183         ssize_t error;
184 
185         error = user_path_walk(path, &nd);
186         if (error)
187                 return error;
188         error = getxattr(nd.dentry, name, value, size);
189         path_release(&nd);
190         return error;
191 }
192 
193 asmlinkage ssize_t
194 sys_lgetxattr(char __user *path, char __user *name, void __user *value,
195               size_t size)
196 {
197         struct nameidata nd;
198         ssize_t error;
199 
200         error = user_path_walk_link(path, &nd);
201         if (error)
202                 return error;
203         error = getxattr(nd.dentry, name, value, size);
204         path_release(&nd);
205         return error;
206 }
207 
208 asmlinkage ssize_t
209 sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
210 {
211         struct file *f;
212         ssize_t error = -EBADF;
213 
214         f = fget(fd);
215         if (!f)
216                 return error;
217         error = getxattr(f->f_dentry, name, value, size);
218         fput(f);
219         return error;
220 }
221 
222 /*
223  * Extended attribute LIST operations
224  */
225 static ssize_t
226 listxattr(struct dentry *d, char __user *list, size_t size)
227 {
228         ssize_t error;
229         char *klist;
230 
231         klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
232         if (IS_ERR(klist))
233                 return PTR_ERR(klist);
234 
235         error = -EOPNOTSUPP;
236         if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
237                 error = security_inode_listxattr(d);
238                 if (error)
239                         goto out;
240                 error = d->d_inode->i_op->listxattr(d, klist, size);
241         }
242 
243         if (klist && error > 0)
244                 if (copy_to_user(list, klist, error))
245                         error = -EFAULT;
246 out:
247         xattr_free(klist, size);
248         return error;
249 }
250 
251 asmlinkage ssize_t
252 sys_listxattr(char __user *path, char __user *list, size_t size)
253 {
254         struct nameidata nd;
255         ssize_t error;
256 
257         error = user_path_walk(path, &nd);
258         if (error)
259                 return error;
260         error = listxattr(nd.dentry, list, size);
261         path_release(&nd);
262         return error;
263 }
264 
265 asmlinkage ssize_t
266 sys_llistxattr(char __user *path, char __user *list, size_t size)
267 {
268         struct nameidata nd;
269         ssize_t error;
270 
271         error = user_path_walk_link(path, &nd);
272         if (error)
273                 return error;
274         error = listxattr(nd.dentry, list, size);
275         path_release(&nd);
276         return error;
277 }
278 
279 asmlinkage ssize_t
280 sys_flistxattr(int fd, char __user *list, size_t size)
281 {
282         struct file *f;
283         ssize_t error = -EBADF;
284 
285         f = fget(fd);
286         if (!f)
287                 return error;
288         error = listxattr(f->f_dentry, list, size);
289         fput(f);
290         return error;
291 }
292 
293 /*
294  * Extended attribute REMOVE operations
295  */
296 static long
297 removexattr(struct dentry *d, char __user *name)
298 {
299         int error;
300         char kname[XATTR_NAME_MAX + 1];
301 
302         error = strncpy_from_user(kname, name, sizeof(kname));
303         if (error == 0 || error == sizeof(kname))
304                 error = -ERANGE;
305         if (error < 0)
306                 return error;
307 
308         error = -EOPNOTSUPP;
309         if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
310                 error = security_inode_removexattr(d, kname);
311                 if (error)
312                         goto out;
313                 down(&d->d_inode->i_sem);
314                 error = d->d_inode->i_op->removexattr(d, kname);
315                 up(&d->d_inode->i_sem);
316         }
317 out:
318         return error;
319 }
320 
321 asmlinkage long
322 sys_removexattr(char __user *path, char __user *name)
323 {
324         struct nameidata nd;
325         int error;
326 
327         error = user_path_walk(path, &nd);
328         if (error)
329                 return error;
330         error = removexattr(nd.dentry, name);
331         path_release(&nd);
332         return error;
333 }
334 
335 asmlinkage long
336 sys_lremovexattr(char __user *path, char __user *name)
337 {
338         struct nameidata nd;
339         int error;
340 
341         error = user_path_walk_link(path, &nd);
342         if (error)
343                 return error;
344         error = removexattr(nd.dentry, name);
345         path_release(&nd);
346         return error;
347 }
348 
349 asmlinkage long
350 sys_fremovexattr(int fd, char __user *name)
351 {
352         struct file *f;
353         int error = -EBADF;
354 
355         f = fget(fd);
356         if (!f)
357                 return error;
358         error = removexattr(f->f_dentry, name);
359         fput(f);
360         return error;
361 }
362 

~ [ 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