hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/fs/sysfs/file.c
....@@ -6,7 +6,7 @@
66 * Copyright (c) 2007 SUSE Linux Products GmbH
77 * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
88 *
9
- * Please see Documentation/filesystems/sysfs.txt for more information.
9
+ * Please see Documentation/filesystems/sysfs.rst for more information.
1010 */
1111
1212 #include <linux/module.h>
....@@ -15,12 +15,9 @@
1515 #include <linux/list.h>
1616 #include <linux/mutex.h>
1717 #include <linux/seq_file.h>
18
-#ifndef __GENKSYMS__
1918 #include <linux/mm.h>
20
-#endif
2119
2220 #include "sysfs.h"
23
-#include "../kernfs/kernfs-internal.h"
2421
2522 /*
2623 * Determine ktype->sysfs_ops for the given kernfs_node. This function
....@@ -328,7 +325,8 @@
328325 kuid_t uid;
329326 kgid_t gid;
330327
331
- BUG_ON(!kobj || !kobj->sd || !attr);
328
+ if (WARN_ON(!kobj || !kobj->sd || !attr))
329
+ return -EINVAL;
332330
333331 kobject_get_ownership(kobj, &uid, &gid);
334332 return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode,
....@@ -337,7 +335,7 @@
337335 }
338336 EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
339337
340
-int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
338
+int sysfs_create_files(struct kobject *kobj, const struct attribute * const *ptr)
341339 {
342340 int err = 0;
343341 int i;
....@@ -495,10 +493,12 @@
495493 kernfs_put(kn);
496494 return ret;
497495 }
496
+EXPORT_SYMBOL_GPL(sysfs_remove_file_self);
498497
499
-void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
498
+void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *ptr)
500499 {
501500 int i;
501
+
502502 for (i = 0; ptr[i]; i++)
503503 sysfs_remove_file(kobj, ptr[i]);
504504 }
....@@ -540,7 +540,8 @@
540540 kuid_t uid;
541541 kgid_t gid;
542542
543
- BUG_ON(!kobj || !kobj->sd || !attr);
543
+ if (WARN_ON(!kobj || !kobj->sd || !attr))
544
+ return -EINVAL;
544545
545546 kobject_get_ownership(kobj, &uid, &gid);
546547 return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true,
....@@ -560,6 +561,154 @@
560561 }
561562 EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
562563
564
+static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid,
565
+ kgid_t kgid)
566
+{
567
+ struct iattr newattrs = {
568
+ .ia_valid = ATTR_UID | ATTR_GID,
569
+ .ia_uid = kuid,
570
+ .ia_gid = kgid,
571
+ };
572
+ return kernfs_setattr(kn, &newattrs);
573
+}
574
+
575
+/**
576
+ * sysfs_link_change_owner - change owner of a sysfs file.
577
+ * @kobj: object of the kernfs_node the symlink is located in.
578
+ * @targ: object of the kernfs_node the symlink points to.
579
+ * @name: name of the link.
580
+ * @kuid: new owner's kuid
581
+ * @kgid: new owner's kgid
582
+ *
583
+ * This function looks up the sysfs symlink entry @name under @kobj and changes
584
+ * the ownership to @kuid/@kgid. The symlink is looked up in the namespace of
585
+ * @targ.
586
+ *
587
+ * Returns 0 on success or error code on failure.
588
+ */
589
+int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
590
+ const char *name, kuid_t kuid, kgid_t kgid)
591
+{
592
+ struct kernfs_node *kn = NULL;
593
+ int error;
594
+
595
+ if (!name || !kobj->state_in_sysfs || !targ->state_in_sysfs)
596
+ return -EINVAL;
597
+
598
+ error = -ENOENT;
599
+ kn = kernfs_find_and_get_ns(kobj->sd, name, targ->sd->ns);
600
+ if (!kn)
601
+ goto out;
602
+
603
+ error = -EINVAL;
604
+ if (kernfs_type(kn) != KERNFS_LINK)
605
+ goto out;
606
+ if (kn->symlink.target_kn->priv != targ)
607
+ goto out;
608
+
609
+ error = internal_change_owner(kn, kuid, kgid);
610
+
611
+out:
612
+ kernfs_put(kn);
613
+ return error;
614
+}
615
+
616
+/**
617
+ * sysfs_file_change_owner - change owner of a sysfs file.
618
+ * @kobj: object.
619
+ * @name: name of the file to change.
620
+ * @kuid: new owner's kuid
621
+ * @kgid: new owner's kgid
622
+ *
623
+ * This function looks up the sysfs entry @name under @kobj and changes the
624
+ * ownership to @kuid/@kgid.
625
+ *
626
+ * Returns 0 on success or error code on failure.
627
+ */
628
+int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid,
629
+ kgid_t kgid)
630
+{
631
+ struct kernfs_node *kn;
632
+ int error;
633
+
634
+ if (!name)
635
+ return -EINVAL;
636
+
637
+ if (!kobj->state_in_sysfs)
638
+ return -EINVAL;
639
+
640
+ kn = kernfs_find_and_get(kobj->sd, name);
641
+ if (!kn)
642
+ return -ENOENT;
643
+
644
+ error = internal_change_owner(kn, kuid, kgid);
645
+
646
+ kernfs_put(kn);
647
+
648
+ return error;
649
+}
650
+EXPORT_SYMBOL_GPL(sysfs_file_change_owner);
651
+
652
+/**
653
+ * sysfs_change_owner - change owner of the given object.
654
+ * @kobj: object.
655
+ * @kuid: new owner's kuid
656
+ * @kgid: new owner's kgid
657
+ *
658
+ * Change the owner of the default directory, files, groups, and attributes of
659
+ * @kobj to @kuid/@kgid. Note that sysfs_change_owner mirrors how the sysfs
660
+ * entries for a kobject are added by driver core. In summary,
661
+ * sysfs_change_owner() takes care of the default directory entry for @kobj,
662
+ * the default attributes associated with the ktype of @kobj and the default
663
+ * attributes associated with the ktype of @kobj.
664
+ * Additional properties not added by driver core have to be changed by the
665
+ * driver or subsystem which created them. This is similar to how
666
+ * driver/subsystem specific entries are removed.
667
+ *
668
+ * Returns 0 on success or error code on failure.
669
+ */
670
+int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid)
671
+{
672
+ int error;
673
+ const struct kobj_type *ktype;
674
+
675
+ if (!kobj->state_in_sysfs)
676
+ return -EINVAL;
677
+
678
+ /* Change the owner of the kobject itself. */
679
+ error = internal_change_owner(kobj->sd, kuid, kgid);
680
+ if (error)
681
+ return error;
682
+
683
+ ktype = get_ktype(kobj);
684
+ if (ktype) {
685
+ struct attribute **kattr;
686
+
687
+ /*
688
+ * Change owner of the default attributes associated with the
689
+ * ktype of @kobj.
690
+ */
691
+ for (kattr = ktype->default_attrs; kattr && *kattr; kattr++) {
692
+ error = sysfs_file_change_owner(kobj, (*kattr)->name,
693
+ kuid, kgid);
694
+ if (error)
695
+ return error;
696
+ }
697
+
698
+ /*
699
+ * Change owner of the default groups associated with the
700
+ * ktype of @kobj.
701
+ */
702
+ error = sysfs_groups_change_owner(kobj, ktype->default_groups,
703
+ kuid, kgid);
704
+ if (error)
705
+ return error;
706
+ }
707
+
708
+ return 0;
709
+}
710
+EXPORT_SYMBOL_GPL(sysfs_change_owner);
711
+
563712 /**
564713 * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer.
565714 * @buf: start of PAGE_SIZE buffer.