int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
 {
        struct kernfs_node *parent, *kn;
+       kuid_t uid;
+       kgid_t gid;
 
        BUG_ON(!kobj);
 
        if (!parent)
                return -ENOENT;
 
+       kobject_get_ownership(kobj, &uid, &gid);
+
        kn = kernfs_create_dir_ns(parent, kobject_name(kobj),
-                                 S_IRWXU | S_IRUGO | S_IXUGO,
-                                 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
+                                 S_IRWXU | S_IRUGO | S_IXUGO, uid, gid,
                                  kobj, ns);
        if (IS_ERR(kn)) {
                if (PTR_ERR(kn) == -EEXIST)
 
 
 int sysfs_add_file_mode_ns(struct kernfs_node *parent,
                           const struct attribute *attr, bool is_bin,
-                          umode_t mode, const void *ns)
+                          umode_t mode, kuid_t uid, kgid_t gid, const void *ns)
 {
        struct lock_class_key *key = NULL;
        const struct kernfs_ops *ops;
        if (!attr->ignore_lockdep)
                key = attr->key ?: (struct lock_class_key *)&attr->skey;
 #endif
-       kn = __kernfs_create_file(parent, attr->name,
-                                 mode & 0777, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
+
+       kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
                                  size, ops, (void *)attr, ns, key);
        if (IS_ERR(kn)) {
                if (PTR_ERR(kn) == -EEXIST)
        return 0;
 }
 
-int sysfs_add_file(struct kernfs_node *parent, const struct attribute *attr,
-                  bool is_bin)
-{
-       return sysfs_add_file_mode_ns(parent, attr, is_bin, attr->mode, NULL);
-}
-
 /**
  * sysfs_create_file_ns - create an attribute file for an object with custom ns
  * @kobj: object we're creating for
 int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
                         const void *ns)
 {
+       kuid_t uid;
+       kgid_t gid;
+
        BUG_ON(!kobj || !kobj->sd || !attr);
 
-       return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode, ns);
+       kobject_get_ownership(kobj, &uid, &gid);
+       return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode,
+                                     uid, gid, ns);
 
 }
 EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
                const struct attribute *attr, const char *group)
 {
        struct kernfs_node *parent;
+       kuid_t uid;
+       kgid_t gid;
        int error;
 
        if (group) {
        if (!parent)
                return -ENOENT;
 
-       error = sysfs_add_file(parent, attr, false);
+       kobject_get_ownership(kobj, &uid, &gid);
+       error = sysfs_add_file_mode_ns(kobj->sd, attr, false,
+                                      attr->mode, uid, gid, NULL);
        kernfs_put(parent);
 
        return error;
 int sysfs_create_bin_file(struct kobject *kobj,
                          const struct bin_attribute *attr)
 {
+       kuid_t uid;
+       kgid_t gid;
+
        BUG_ON(!kobj || !kobj->sd || !attr);
 
-       return sysfs_add_file(kobj->sd, &attr->attr, true);
+       kobject_get_ownership(kobj, &uid, &gid);
+       return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true,
+                                     attr->attr.mode, uid, gid, NULL);
 }
 EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
 
 
 }
 
 static int create_files(struct kernfs_node *parent, struct kobject *kobj,
+                       kuid_t uid, kgid_t gid,
                        const struct attribute_group *grp, int update)
 {
        struct attribute *const *attr;
 
                        mode &= SYSFS_PREALLOC | 0664;
                        error = sysfs_add_file_mode_ns(parent, *attr, false,
-                                                      mode, NULL);
+                                                      mode, uid, gid, NULL);
                        if (unlikely(error))
                                break;
                }
                        mode &= SYSFS_PREALLOC | 0664;
                        error = sysfs_add_file_mode_ns(parent,
                                        &(*bin_attr)->attr, true,
-                                       mode, NULL);
+                                       mode,
+                                       uid, gid, NULL);
                        if (error)
                                break;
                }
                                 const struct attribute_group *grp)
 {
        struct kernfs_node *kn;
+       kuid_t uid;
+       kgid_t gid;
        int error;
 
        BUG_ON(!kobj || (!update && !kobj->sd));
                        kobj->name, grp->name ?: "");
                return -EINVAL;
        }
+       kobject_get_ownership(kobj, &uid, &gid);
        if (grp->name) {
-               kn = kernfs_create_dir(kobj->sd, grp->name,
-                                      S_IRWXU | S_IRUGO | S_IXUGO, kobj);
+               kn = kernfs_create_dir_ns(kobj->sd, grp->name,
+                                         S_IRWXU | S_IRUGO | S_IXUGO,
+                                         uid, gid, kobj, NULL);
                if (IS_ERR(kn)) {
                        if (PTR_ERR(kn) == -EEXIST)
                                sysfs_warn_dup(kobj->sd, grp->name);
        } else
                kn = kobj->sd;
        kernfs_get(kn);
-       error = create_files(kn, kobj, grp, update);
+       error = create_files(kn, kobj, uid, gid, grp, update);
        if (error) {
                if (grp->name)
                        kernfs_remove(kn);
                       const struct attribute_group *grp)
 {
        struct kernfs_node *parent;
+       kuid_t uid;
+       kgid_t gid;
        int error = 0;
        struct attribute *const *attr;
        int i;
        if (!parent)
                return -ENOENT;
 
+       kobject_get_ownership(kobj, &uid, &gid);
+
        for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
-               error = sysfs_add_file(parent, *attr, false);
+               error = sysfs_add_file_mode_ns(parent, *attr, false,
+                                              (*attr)->mode, uid, gid, NULL);
        if (error) {
                while (--i >= 0)
                        kernfs_remove_by_name(parent, (*--attr)->name);
 
 /*
  * file.c
  */
-int sysfs_add_file(struct kernfs_node *parent,
-                  const struct attribute *attr, bool is_bin);
 int sysfs_add_file_mode_ns(struct kernfs_node *parent,
                           const struct attribute *attr, bool is_bin,
-                          umode_t amode, const void *ns);
+                          umode_t amode, kuid_t uid, kgid_t gid,
+                          const void *ns);
 
 /*
  * symlink.c
 
 #include <linux/wait.h>
 #include <linux/atomic.h>
 #include <linux/workqueue.h>
+#include <linux/uidgid.h>
 
 #define UEVENT_HELPER_PATH_LEN         256
 #define UEVENT_NUM_ENVP                        32      /* number of env pointers */
 extern void kobject_put(struct kobject *kobj);
 
 extern const void *kobject_namespace(struct kobject *kobj);
+extern void kobject_get_ownership(struct kobject *kobj,
+                                 kuid_t *uid, kgid_t *gid);
 extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
 
 struct kobj_type {
        struct attribute **default_attrs;
        const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
        const void *(*namespace)(struct kobject *kobj);
+       void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
 };
 
 struct kobj_uevent_env {
 
        return kobj->ktype->namespace(kobj);
 }
 
+/**
+ * kobject_get_ownership - get sysfs ownership data for @kobj
+ * @kobj: kobject in question
+ * @uid: kernel user ID for sysfs objects
+ * @gid: kernel group ID for sysfs objects
+ *
+ * Returns initial uid/gid pair that should be used when creating sysfs
+ * representation of given kobject. Normally used to adjust ownership of
+ * objects in a container.
+ */
+void kobject_get_ownership(struct kobject *kobj, kuid_t *uid, kgid_t *gid)
+{
+       *uid = GLOBAL_ROOT_UID;
+       *gid = GLOBAL_ROOT_GID;
+
+       if (kobj->ktype->get_ownership)
+               kobj->ktype->get_ownership(kobj, uid, gid);
+}
+
 /*
  * populate_dir - populate directory with attributes.
  * @kobj: object we're working on.