1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * fs/sysfs/file.c - sysfs regular (text) file implementation
4 *
5 * Copyright (c) 2001-3 Patrick Mochel
6 * Copyright (c) 2007 SUSE Linux Products GmbH
7 * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
8 *
9 * Please see Documentation/filesystems/sysfs.rst for more information.
10 */
11
12 #include <linux/module.h>
13 #include <linux/kobject.h>
14 #include <linux/slab.h>
15 #include <linux/list.h>
16 #include <linux/mutex.h>
17 #include <linux/seq_file.h>
18 #include <linux/mm.h>
19
20 #include "sysfs.h"
21
sysfs_file_kobj(struct kernfs_node * kn)22 static struct kobject *sysfs_file_kobj(struct kernfs_node *kn)
23 {
24 guard(rcu)();
25 return rcu_dereference(kn->__parent)->priv;
26 }
27
28 /*
29 * Determine ktype->sysfs_ops for the given kernfs_node. This function
30 * must be called while holding an active reference.
31 */
sysfs_file_ops(struct kernfs_node * kn)32 static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn)
33 {
34 struct kobject *kobj = sysfs_file_kobj(kn);
35
36 if (kn->flags & KERNFS_LOCKDEP)
37 lockdep_assert_held(kn);
38 return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
39 }
40
41 /*
42 * Reads on sysfs are handled through seq_file, which takes care of hairy
43 * details like buffering and seeking. The following function pipes
44 * sysfs_ops->show() result through seq_file.
45 */
sysfs_kf_seq_show(struct seq_file * sf,void * v)46 static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
47 {
48 struct kernfs_open_file *of = sf->private;
49 struct kobject *kobj = sysfs_file_kobj(of->kn);
50 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
51 ssize_t count;
52 char *buf;
53
54 if (WARN_ON_ONCE(!ops->show))
55 return -EINVAL;
56
57 /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
58 count = seq_get_buf(sf, &buf);
59 if (count < PAGE_SIZE) {
60 seq_commit(sf, -1);
61 return 0;
62 }
63 memset(buf, 0, PAGE_SIZE);
64
65 count = ops->show(kobj, of->kn->priv, buf);
66 if (count < 0)
67 return count;
68
69 /*
70 * The code works fine with PAGE_SIZE return but it's likely to
71 * indicate truncated result or overflow in normal use cases.
72 */
73 if (count >= (ssize_t)PAGE_SIZE) {
74 printk("fill_read_buffer: %pS returned bad count\n",
75 ops->show);
76 /* Try to struggle along */
77 count = PAGE_SIZE - 1;
78 }
79 seq_commit(sf, count);
80 return 0;
81 }
82
sysfs_kf_bin_read(struct kernfs_open_file * of,char * buf,size_t count,loff_t pos)83 static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
84 size_t count, loff_t pos)
85 {
86 struct bin_attribute *battr = of->kn->priv;
87 struct kobject *kobj = sysfs_file_kobj(of->kn);
88 loff_t size = file_inode(of->file)->i_size;
89
90 if (!count)
91 return 0;
92
93 if (size) {
94 if (pos >= size)
95 return 0;
96 if (pos + count > size)
97 count = size - pos;
98 }
99
100 if (!battr->read && !battr->read_new)
101 return -EIO;
102
103 if (battr->read_new)
104 return battr->read_new(of->file, kobj, battr, buf, pos, count);
105
106 return battr->read(of->file, kobj, battr, buf, pos, count);
107 }
108
109 /* kernfs read callback for regular sysfs files with pre-alloc */
sysfs_kf_read(struct kernfs_open_file * of,char * buf,size_t count,loff_t pos)110 static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
111 size_t count, loff_t pos)
112 {
113 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
114 struct kobject *kobj = sysfs_file_kobj(of->kn);
115 ssize_t len;
116
117 /*
118 * If buf != of->prealloc_buf, we don't know how
119 * large it is, so cannot safely pass it to ->show
120 */
121 if (WARN_ON_ONCE(buf != of->prealloc_buf))
122 return 0;
123 len = ops->show(kobj, of->kn->priv, buf);
124 if (len < 0)
125 return len;
126 if (pos) {
127 if (len <= pos)
128 return 0;
129 len -= pos;
130 memmove(buf, buf + pos, len);
131 }
132 return min_t(ssize_t, count, len);
133 }
134
135 /* kernfs write callback for regular sysfs files */
sysfs_kf_write(struct kernfs_open_file * of,char * buf,size_t count,loff_t pos)136 static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
137 size_t count, loff_t pos)
138 {
139 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
140 struct kobject *kobj = sysfs_file_kobj(of->kn);
141
142 if (!count)
143 return 0;
144
145 return ops->store(kobj, of->kn->priv, buf, count);
146 }
147
148 /* kernfs write callback for bin sysfs files */
sysfs_kf_bin_write(struct kernfs_open_file * of,char * buf,size_t count,loff_t pos)149 static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
150 size_t count, loff_t pos)
151 {
152 struct bin_attribute *battr = of->kn->priv;
153 struct kobject *kobj = sysfs_file_kobj(of->kn);
154 loff_t size = file_inode(of->file)->i_size;
155
156 if (size) {
157 if (size <= pos)
158 return -EFBIG;
159 count = min_t(ssize_t, count, size - pos);
160 }
161 if (!count)
162 return 0;
163
164 if (!battr->write && !battr->write_new)
165 return -EIO;
166
167 if (battr->write_new)
168 return battr->write_new(of->file, kobj, battr, buf, pos, count);
169
170 return battr->write(of->file, kobj, battr, buf, pos, count);
171 }
172
sysfs_kf_bin_mmap(struct kernfs_open_file * of,struct vm_area_struct * vma)173 static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
174 struct vm_area_struct *vma)
175 {
176 struct bin_attribute *battr = of->kn->priv;
177 struct kobject *kobj = sysfs_file_kobj(of->kn);
178
179 return battr->mmap(of->file, kobj, battr, vma);
180 }
181
sysfs_kf_bin_llseek(struct kernfs_open_file * of,loff_t offset,int whence)182 static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset,
183 int whence)
184 {
185 struct bin_attribute *battr = of->kn->priv;
186 struct kobject *kobj = sysfs_file_kobj(of->kn);
187
188 if (battr->llseek)
189 return battr->llseek(of->file, kobj, battr, offset, whence);
190 else
191 return generic_file_llseek(of->file, offset, whence);
192 }
193
sysfs_kf_bin_open(struct kernfs_open_file * of)194 static int sysfs_kf_bin_open(struct kernfs_open_file *of)
195 {
196 struct bin_attribute *battr = of->kn->priv;
197
198 if (battr->f_mapping)
199 of->file->f_mapping = battr->f_mapping();
200
201 return 0;
202 }
203
sysfs_notify(struct kobject * kobj,const char * dir,const char * attr)204 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr)
205 {
206 struct kernfs_node *kn = kobj->sd, *tmp;
207
208 if (kn && dir)
209 kn = kernfs_find_and_get(kn, dir);
210 else
211 kernfs_get(kn);
212
213 if (kn && attr) {
214 tmp = kernfs_find_and_get(kn, attr);
215 kernfs_put(kn);
216 kn = tmp;
217 }
218
219 if (kn) {
220 kernfs_notify(kn);
221 kernfs_put(kn);
222 }
223 }
224 EXPORT_SYMBOL_GPL(sysfs_notify);
225
226 static const struct kernfs_ops sysfs_file_kfops_empty = {
227 };
228
229 static const struct kernfs_ops sysfs_file_kfops_ro = {
230 .seq_show = sysfs_kf_seq_show,
231 };
232
233 static const struct kernfs_ops sysfs_file_kfops_wo = {
234 .write = sysfs_kf_write,
235 };
236
237 static const struct kernfs_ops sysfs_file_kfops_rw = {
238 .seq_show = sysfs_kf_seq_show,
239 .write = sysfs_kf_write,
240 };
241
242 static const struct kernfs_ops sysfs_prealloc_kfops_ro = {
243 .read = sysfs_kf_read,
244 .prealloc = true,
245 };
246
247 static const struct kernfs_ops sysfs_prealloc_kfops_wo = {
248 .write = sysfs_kf_write,
249 .prealloc = true,
250 };
251
252 static const struct kernfs_ops sysfs_prealloc_kfops_rw = {
253 .read = sysfs_kf_read,
254 .write = sysfs_kf_write,
255 .prealloc = true,
256 };
257
258 static const struct kernfs_ops sysfs_bin_kfops_ro = {
259 .read = sysfs_kf_bin_read,
260 };
261
262 static const struct kernfs_ops sysfs_bin_kfops_wo = {
263 .write = sysfs_kf_bin_write,
264 };
265
266 static const struct kernfs_ops sysfs_bin_kfops_rw = {
267 .read = sysfs_kf_bin_read,
268 .write = sysfs_kf_bin_write,
269 };
270
271 static const struct kernfs_ops sysfs_bin_kfops_mmap = {
272 .read = sysfs_kf_bin_read,
273 .write = sysfs_kf_bin_write,
274 .mmap = sysfs_kf_bin_mmap,
275 .open = sysfs_kf_bin_open,
276 .llseek = sysfs_kf_bin_llseek,
277 };
278
sysfs_add_file_mode_ns(struct kernfs_node * parent,const struct attribute * attr,umode_t mode,kuid_t uid,kgid_t gid,const void * ns)279 int sysfs_add_file_mode_ns(struct kernfs_node *parent,
280 const struct attribute *attr, umode_t mode, kuid_t uid,
281 kgid_t gid, const void *ns)
282 {
283 struct kobject *kobj = parent->priv;
284 const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
285 struct lock_class_key *key = NULL;
286 const struct kernfs_ops *ops = NULL;
287 struct kernfs_node *kn;
288
289 /* every kobject with an attribute needs a ktype assigned */
290 if (WARN(!sysfs_ops, KERN_ERR
291 "missing sysfs attribute operations for kobject: %s\n",
292 kobject_name(kobj)))
293 return -EINVAL;
294
295 if (mode & SYSFS_PREALLOC) {
296 if (sysfs_ops->show && sysfs_ops->store)
297 ops = &sysfs_prealloc_kfops_rw;
298 else if (sysfs_ops->show)
299 ops = &sysfs_prealloc_kfops_ro;
300 else if (sysfs_ops->store)
301 ops = &sysfs_prealloc_kfops_wo;
302 } else {
303 if (sysfs_ops->show && sysfs_ops->store)
304 ops = &sysfs_file_kfops_rw;
305 else if (sysfs_ops->show)
306 ops = &sysfs_file_kfops_ro;
307 else if (sysfs_ops->store)
308 ops = &sysfs_file_kfops_wo;
309 }
310
311 if (!ops)
312 ops = &sysfs_file_kfops_empty;
313
314 #ifdef CONFIG_DEBUG_LOCK_ALLOC
315 if (!attr->ignore_lockdep)
316 key = attr->key ?: (struct lock_class_key *)&attr->skey;
317 #endif
318
319 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
320 PAGE_SIZE, ops, (void *)attr, ns, key);
321 if (IS_ERR(kn)) {
322 if (PTR_ERR(kn) == -EEXIST)
323 sysfs_warn_dup(parent, attr->name);
324 return PTR_ERR(kn);
325 }
326 return 0;
327 }
328
sysfs_add_bin_file_mode_ns(struct kernfs_node * parent,const struct bin_attribute * battr,umode_t mode,size_t size,kuid_t uid,kgid_t gid,const void * ns)329 int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
330 const struct bin_attribute *battr, umode_t mode, size_t size,
331 kuid_t uid, kgid_t gid, const void *ns)
332 {
333 const struct attribute *attr = &battr->attr;
334 struct lock_class_key *key = NULL;
335 const struct kernfs_ops *ops;
336 struct kernfs_node *kn;
337
338 if (battr->read && battr->read_new)
339 return -EINVAL;
340
341 if (battr->write && battr->write_new)
342 return -EINVAL;
343
344 if (battr->mmap)
345 ops = &sysfs_bin_kfops_mmap;
346 else if ((battr->read || battr->read_new) && (battr->write || battr->write_new))
347 ops = &sysfs_bin_kfops_rw;
348 else if (battr->read || battr->read_new)
349 ops = &sysfs_bin_kfops_ro;
350 else if (battr->write || battr->write_new)
351 ops = &sysfs_bin_kfops_wo;
352 else
353 ops = &sysfs_file_kfops_empty;
354
355 #ifdef CONFIG_DEBUG_LOCK_ALLOC
356 if (!attr->ignore_lockdep)
357 key = attr->key ?: (struct lock_class_key *)&attr->skey;
358 #endif
359
360 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
361 size, ops, (void *)attr, ns, key);
362 if (IS_ERR(kn)) {
363 if (PTR_ERR(kn) == -EEXIST)
364 sysfs_warn_dup(parent, attr->name);
365 return PTR_ERR(kn);
366 }
367 return 0;
368 }
369
370 /**
371 * sysfs_create_file_ns - create an attribute file for an object with custom ns
372 * @kobj: object we're creating for
373 * @attr: attribute descriptor
374 * @ns: namespace the new file should belong to
375 */
sysfs_create_file_ns(struct kobject * kobj,const struct attribute * attr,const void * ns)376 int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
377 const void *ns)
378 {
379 kuid_t uid;
380 kgid_t gid;
381
382 if (WARN_ON(!kobj || !kobj->sd || !attr))
383 return -EINVAL;
384
385 kobject_get_ownership(kobj, &uid, &gid);
386 return sysfs_add_file_mode_ns(kobj->sd, attr, attr->mode, uid, gid, ns);
387 }
388 EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
389
sysfs_create_files(struct kobject * kobj,const struct attribute * const * ptr)390 int sysfs_create_files(struct kobject *kobj, const struct attribute * const *ptr)
391 {
392 int err = 0;
393 int i;
394
395 for (i = 0; ptr[i] && !err; i++)
396 err = sysfs_create_file(kobj, ptr[i]);
397 if (err)
398 while (--i >= 0)
399 sysfs_remove_file(kobj, ptr[i]);
400 return err;
401 }
402 EXPORT_SYMBOL_GPL(sysfs_create_files);
403
404 /**
405 * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
406 * @kobj: object we're acting for.
407 * @attr: attribute descriptor.
408 * @group: group name.
409 */
sysfs_add_file_to_group(struct kobject * kobj,const struct attribute * attr,const char * group)410 int sysfs_add_file_to_group(struct kobject *kobj,
411 const struct attribute *attr, const char *group)
412 {
413 struct kernfs_node *parent;
414 kuid_t uid;
415 kgid_t gid;
416 int error;
417
418 if (group) {
419 parent = kernfs_find_and_get(kobj->sd, group);
420 } else {
421 parent = kobj->sd;
422 kernfs_get(parent);
423 }
424
425 if (!parent)
426 return -ENOENT;
427
428 kobject_get_ownership(kobj, &uid, &gid);
429 error = sysfs_add_file_mode_ns(parent, attr, attr->mode, uid, gid,
430 NULL);
431 kernfs_put(parent);
432
433 return error;
434 }
435 EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
436
437 /**
438 * sysfs_chmod_file - update the modified mode value on an object attribute.
439 * @kobj: object we're acting for.
440 * @attr: attribute descriptor.
441 * @mode: file permissions.
442 *
443 */
sysfs_chmod_file(struct kobject * kobj,const struct attribute * attr,umode_t mode)444 int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
445 umode_t mode)
446 {
447 struct kernfs_node *kn;
448 struct iattr newattrs;
449 int rc;
450
451 kn = kernfs_find_and_get(kobj->sd, attr->name);
452 if (!kn)
453 return -ENOENT;
454
455 newattrs.ia_mode = (mode & S_IALLUGO) | (kn->mode & ~S_IALLUGO);
456 newattrs.ia_valid = ATTR_MODE;
457
458 rc = kernfs_setattr(kn, &newattrs);
459
460 kernfs_put(kn);
461 return rc;
462 }
463 EXPORT_SYMBOL_GPL(sysfs_chmod_file);
464
465 /**
466 * sysfs_break_active_protection - break "active" protection
467 * @kobj: The kernel object @attr is associated with.
468 * @attr: The attribute to break the "active" protection for.
469 *
470 * With sysfs, just like kernfs, deletion of an attribute is postponed until
471 * all active .show() and .store() callbacks have finished unless this function
472 * is called. Hence this function is useful in methods that implement self
473 * deletion.
474 */
sysfs_break_active_protection(struct kobject * kobj,const struct attribute * attr)475 struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
476 const struct attribute *attr)
477 {
478 struct kernfs_node *kn;
479
480 kobject_get(kobj);
481 kn = kernfs_find_and_get(kobj->sd, attr->name);
482 if (kn)
483 kernfs_break_active_protection(kn);
484 else
485 kobject_put(kobj);
486 return kn;
487 }
488 EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
489
490 /**
491 * sysfs_unbreak_active_protection - restore "active" protection
492 * @kn: Pointer returned by sysfs_break_active_protection().
493 *
494 * Undo the effects of sysfs_break_active_protection(). Since this function
495 * calls kernfs_put() on the kernfs node that corresponds to the 'attr'
496 * argument passed to sysfs_break_active_protection() that attribute may have
497 * been removed between the sysfs_break_active_protection() and
498 * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after
499 * this function has returned.
500 */
sysfs_unbreak_active_protection(struct kernfs_node * kn)501 void sysfs_unbreak_active_protection(struct kernfs_node *kn)
502 {
503 struct kobject *kobj = sysfs_file_kobj(kn);
504
505 kernfs_unbreak_active_protection(kn);
506 kernfs_put(kn);
507 kobject_put(kobj);
508 }
509 EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
510
511 /**
512 * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
513 * @kobj: object we're acting for
514 * @attr: attribute descriptor
515 * @ns: namespace tag of the file to remove
516 *
517 * Hash the attribute name and namespace tag and kill the victim.
518 */
sysfs_remove_file_ns(struct kobject * kobj,const struct attribute * attr,const void * ns)519 void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
520 const void *ns)
521 {
522 struct kernfs_node *parent = kobj->sd;
523
524 kernfs_remove_by_name_ns(parent, attr->name, ns);
525 }
526 EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
527
528 /**
529 * sysfs_remove_file_self - remove an object attribute from its own method
530 * @kobj: object we're acting for
531 * @attr: attribute descriptor
532 *
533 * See kernfs_remove_self() for details.
534 */
sysfs_remove_file_self(struct kobject * kobj,const struct attribute * attr)535 bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr)
536 {
537 struct kernfs_node *parent = kobj->sd;
538 struct kernfs_node *kn;
539 bool ret;
540
541 kn = kernfs_find_and_get(parent, attr->name);
542 if (WARN_ON_ONCE(!kn))
543 return false;
544
545 ret = kernfs_remove_self(kn);
546
547 kernfs_put(kn);
548 return ret;
549 }
550 EXPORT_SYMBOL_GPL(sysfs_remove_file_self);
551
sysfs_remove_files(struct kobject * kobj,const struct attribute * const * ptr)552 void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *ptr)
553 {
554 int i;
555
556 for (i = 0; ptr[i]; i++)
557 sysfs_remove_file(kobj, ptr[i]);
558 }
559 EXPORT_SYMBOL_GPL(sysfs_remove_files);
560
561 /**
562 * sysfs_remove_file_from_group - remove an attribute file from a group.
563 * @kobj: object we're acting for.
564 * @attr: attribute descriptor.
565 * @group: group name.
566 */
sysfs_remove_file_from_group(struct kobject * kobj,const struct attribute * attr,const char * group)567 void sysfs_remove_file_from_group(struct kobject *kobj,
568 const struct attribute *attr, const char *group)
569 {
570 struct kernfs_node *parent;
571
572 if (group) {
573 parent = kernfs_find_and_get(kobj->sd, group);
574 } else {
575 parent = kobj->sd;
576 kernfs_get(parent);
577 }
578
579 if (parent) {
580 kernfs_remove_by_name(parent, attr->name);
581 kernfs_put(parent);
582 }
583 }
584 EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
585
586 /**
587 * sysfs_create_bin_file - create binary file for object.
588 * @kobj: object.
589 * @attr: attribute descriptor.
590 */
sysfs_create_bin_file(struct kobject * kobj,const struct bin_attribute * attr)591 int sysfs_create_bin_file(struct kobject *kobj,
592 const struct bin_attribute *attr)
593 {
594 kuid_t uid;
595 kgid_t gid;
596
597 if (WARN_ON(!kobj || !kobj->sd || !attr))
598 return -EINVAL;
599
600 kobject_get_ownership(kobj, &uid, &gid);
601 return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode,
602 attr->size, uid, gid, NULL);
603 }
604 EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
605
606 /**
607 * sysfs_remove_bin_file - remove binary file for object.
608 * @kobj: object.
609 * @attr: attribute descriptor.
610 */
sysfs_remove_bin_file(struct kobject * kobj,const struct bin_attribute * attr)611 void sysfs_remove_bin_file(struct kobject *kobj,
612 const struct bin_attribute *attr)
613 {
614 kernfs_remove_by_name(kobj->sd, attr->attr.name);
615 }
616 EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
617
internal_change_owner(struct kernfs_node * kn,kuid_t kuid,kgid_t kgid)618 static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid,
619 kgid_t kgid)
620 {
621 struct iattr newattrs = {
622 .ia_valid = ATTR_UID | ATTR_GID,
623 .ia_uid = kuid,
624 .ia_gid = kgid,
625 };
626 return kernfs_setattr(kn, &newattrs);
627 }
628
629 /**
630 * sysfs_link_change_owner - change owner of a sysfs file.
631 * @kobj: object of the kernfs_node the symlink is located in.
632 * @targ: object of the kernfs_node the symlink points to.
633 * @name: name of the link.
634 * @kuid: new owner's kuid
635 * @kgid: new owner's kgid
636 *
637 * This function looks up the sysfs symlink entry @name under @kobj and changes
638 * the ownership to @kuid/@kgid. The symlink is looked up in the namespace of
639 * @targ.
640 *
641 * Returns 0 on success or error code on failure.
642 */
sysfs_link_change_owner(struct kobject * kobj,struct kobject * targ,const char * name,kuid_t kuid,kgid_t kgid)643 int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
644 const char *name, kuid_t kuid, kgid_t kgid)
645 {
646 struct kernfs_node *kn = NULL;
647 int error;
648
649 if (!name || !kobj->state_in_sysfs || !targ->state_in_sysfs)
650 return -EINVAL;
651
652 error = -ENOENT;
653 kn = kernfs_find_and_get_ns(kobj->sd, name, targ->sd->ns);
654 if (!kn)
655 goto out;
656
657 error = -EINVAL;
658 if (kernfs_type(kn) != KERNFS_LINK)
659 goto out;
660 if (kn->symlink.target_kn->priv != targ)
661 goto out;
662
663 error = internal_change_owner(kn, kuid, kgid);
664
665 out:
666 kernfs_put(kn);
667 return error;
668 }
669
670 /**
671 * sysfs_file_change_owner - change owner of a sysfs file.
672 * @kobj: object.
673 * @name: name of the file to change.
674 * @kuid: new owner's kuid
675 * @kgid: new owner's kgid
676 *
677 * This function looks up the sysfs entry @name under @kobj and changes the
678 * ownership to @kuid/@kgid.
679 *
680 * Returns 0 on success or error code on failure.
681 */
sysfs_file_change_owner(struct kobject * kobj,const char * name,kuid_t kuid,kgid_t kgid)682 int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid,
683 kgid_t kgid)
684 {
685 struct kernfs_node *kn;
686 int error;
687
688 if (!name)
689 return -EINVAL;
690
691 if (!kobj->state_in_sysfs)
692 return -EINVAL;
693
694 kn = kernfs_find_and_get(kobj->sd, name);
695 if (!kn)
696 return -ENOENT;
697
698 error = internal_change_owner(kn, kuid, kgid);
699
700 kernfs_put(kn);
701
702 return error;
703 }
704 EXPORT_SYMBOL_GPL(sysfs_file_change_owner);
705
706 /**
707 * sysfs_change_owner - change owner of the given object.
708 * @kobj: object.
709 * @kuid: new owner's kuid
710 * @kgid: new owner's kgid
711 *
712 * Change the owner of the default directory, files, groups, and attributes of
713 * @kobj to @kuid/@kgid. Note that sysfs_change_owner mirrors how the sysfs
714 * entries for a kobject are added by driver core. In summary,
715 * sysfs_change_owner() takes care of the default directory entry for @kobj,
716 * the default attributes associated with the ktype of @kobj and the default
717 * attributes associated with the ktype of @kobj.
718 * Additional properties not added by driver core have to be changed by the
719 * driver or subsystem which created them. This is similar to how
720 * driver/subsystem specific entries are removed.
721 *
722 * Returns 0 on success or error code on failure.
723 */
sysfs_change_owner(struct kobject * kobj,kuid_t kuid,kgid_t kgid)724 int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid)
725 {
726 int error;
727 const struct kobj_type *ktype;
728
729 if (!kobj->state_in_sysfs)
730 return -EINVAL;
731
732 /* Change the owner of the kobject itself. */
733 error = internal_change_owner(kobj->sd, kuid, kgid);
734 if (error)
735 return error;
736
737 ktype = get_ktype(kobj);
738 if (ktype) {
739 /*
740 * Change owner of the default groups associated with the
741 * ktype of @kobj.
742 */
743 error = sysfs_groups_change_owner(kobj, ktype->default_groups,
744 kuid, kgid);
745 if (error)
746 return error;
747 }
748
749 return 0;
750 }
751 EXPORT_SYMBOL_GPL(sysfs_change_owner);
752
753 /**
754 * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer.
755 * @buf: start of PAGE_SIZE buffer.
756 * @fmt: format
757 * @...: optional arguments to @format
758 *
759 *
760 * Returns number of characters written to @buf.
761 */
sysfs_emit(char * buf,const char * fmt,...)762 int sysfs_emit(char *buf, const char *fmt, ...)
763 {
764 va_list args;
765 int len;
766
767 if (WARN(!buf || offset_in_page(buf),
768 "invalid sysfs_emit: buf:%p\n", buf))
769 return 0;
770
771 va_start(args, fmt);
772 len = vscnprintf(buf, PAGE_SIZE, fmt, args);
773 va_end(args);
774
775 return len;
776 }
777 EXPORT_SYMBOL_GPL(sysfs_emit);
778
779 /**
780 * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer.
781 * @buf: start of PAGE_SIZE buffer.
782 * @at: offset in @buf to start write in bytes
783 * @at must be >= 0 && < PAGE_SIZE
784 * @fmt: format
785 * @...: optional arguments to @fmt
786 *
787 *
788 * Returns number of characters written starting at &@buf[@at].
789 */
sysfs_emit_at(char * buf,int at,const char * fmt,...)790 int sysfs_emit_at(char *buf, int at, const char *fmt, ...)
791 {
792 va_list args;
793 int len;
794
795 if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE,
796 "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at))
797 return 0;
798
799 va_start(args, fmt);
800 len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args);
801 va_end(args);
802
803 return len;
804 }
805 EXPORT_SYMBOL_GPL(sysfs_emit_at);
806
807 /**
808 * sysfs_bin_attr_simple_read - read callback to simply copy from memory.
809 * @file: attribute file which is being read.
810 * @kobj: object to which the attribute belongs.
811 * @attr: attribute descriptor.
812 * @buf: destination buffer.
813 * @off: offset in bytes from which to read.
814 * @count: maximum number of bytes to read.
815 *
816 * Simple ->read() callback for bin_attributes backed by a buffer in memory.
817 * The @private and @size members in struct bin_attribute must be set to the
818 * buffer's location and size before the bin_attribute is created in sysfs.
819 *
820 * Bounds check for @off and @count is done in sysfs_kf_bin_read().
821 * Negative value check for @off is done in vfs_setpos() and default_llseek().
822 *
823 * Returns number of bytes written to @buf.
824 */
sysfs_bin_attr_simple_read(struct file * file,struct kobject * kobj,const struct bin_attribute * attr,char * buf,loff_t off,size_t count)825 ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj,
826 const struct bin_attribute *attr, char *buf,
827 loff_t off, size_t count)
828 {
829 memcpy(buf, attr->private + off, count);
830 return count;
831 }
832 EXPORT_SYMBOL_GPL(sysfs_bin_attr_simple_read);
833