aboutsummaryrefslogtreecommitdiff
path: root/ipc/kdbus/metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/kdbus/metadata.c')
-rw-r--r--ipc/kdbus/metadata.c216
1 files changed, 134 insertions, 82 deletions
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
index 79f0e8c7f4a3..ac4135c507c4 100644
--- a/ipc/kdbus/metadata.c
+++ b/ipc/kdbus/metadata.c
@@ -494,101 +494,116 @@ exit_unlock:
}
/**
- * kdbus_meta_proc_fake() - Fill process metadata from faked credentials
- * @mp: Metadata
+ * kdbus_meta_fake_new() - Create fake metadata object
+ *
+ * Return: Pointer to new object on success, ERR_PTR on failure.
+ */
+struct kdbus_meta_fake *kdbus_meta_fake_new(void)
+{
+ struct kdbus_meta_fake *mf;
+
+ mf = kzalloc(sizeof(*mf), GFP_KERNEL);
+ if (!mf)
+ return ERR_PTR(-ENOMEM);
+
+ return mf;
+}
+
+/**
+ * kdbus_meta_fake_free() - Free fake metadata object
+ * @mf: Fake metadata object
+ *
+ * Return: NULL
+ */
+struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf)
+{
+ if (mf) {
+ put_pid(mf->ppid);
+ put_pid(mf->tgid);
+ put_pid(mf->pid);
+ kfree(mf->seclabel);
+ kfree(mf);
+ }
+
+ return NULL;
+}
+
+/**
+ * kdbus_meta_fake_collect() - Fill fake metadata from faked credentials
+ * @mf: Fake metadata object
* @creds: Creds to set, may be %NULL
* @pids: PIDs to set, may be %NULL
* @seclabel: Seclabel to set, may be %NULL
*
* This function takes information stored in @creds, @pids and @seclabel and
- * resolves them to kernel-representations, if possible. A call to this function
- * is considered an alternative to calling kdbus_meta_add_current(), which
- * derives the same information from the 'current' task.
- *
- * This call uses the current task's namespaces to resolve the given
- * information.
+ * resolves them to kernel-representations, if possible. This call uses the
+ * current task's namespaces to resolve the given information.
*
- * Return: 0 on success, negative error number otherwise.
+ * Return: 0 on success, negative error code on failure.
*/
-int kdbus_meta_proc_fake(struct kdbus_meta_proc *mp,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel)
+int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf,
+ const struct kdbus_creds *creds,
+ const struct kdbus_pids *pids,
+ const char *seclabel)
{
- int ret;
-
- if (!mp)
- return 0;
-
- mutex_lock(&mp->lock);
+ if (mf->valid)
+ return -EALREADY;
- if (creds && !(mp->collected & KDBUS_ATTACH_CREDS)) {
+ if (creds) {
struct user_namespace *ns = current_user_ns();
- mp->uid = make_kuid(ns, creds->uid);
- mp->euid = make_kuid(ns, creds->euid);
- mp->suid = make_kuid(ns, creds->suid);
- mp->fsuid = make_kuid(ns, creds->fsuid);
-
- mp->gid = make_kgid(ns, creds->gid);
- mp->egid = make_kgid(ns, creds->egid);
- mp->sgid = make_kgid(ns, creds->sgid);
- mp->fsgid = make_kgid(ns, creds->fsgid);
-
- if ((creds->uid != (uid_t)-1 && !uid_valid(mp->uid)) ||
- (creds->euid != (uid_t)-1 && !uid_valid(mp->euid)) ||
- (creds->suid != (uid_t)-1 && !uid_valid(mp->suid)) ||
- (creds->fsuid != (uid_t)-1 && !uid_valid(mp->fsuid)) ||
- (creds->gid != (gid_t)-1 && !gid_valid(mp->gid)) ||
- (creds->egid != (gid_t)-1 && !gid_valid(mp->egid)) ||
- (creds->sgid != (gid_t)-1 && !gid_valid(mp->sgid)) ||
- (creds->fsgid != (gid_t)-1 && !gid_valid(mp->fsgid))) {
- ret = -EINVAL;
- goto exit_unlock;
- }
-
- mp->valid |= KDBUS_ATTACH_CREDS;
- mp->collected |= KDBUS_ATTACH_CREDS;
+ mf->uid = make_kuid(ns, creds->uid);
+ mf->euid = make_kuid(ns, creds->euid);
+ mf->suid = make_kuid(ns, creds->suid);
+ mf->fsuid = make_kuid(ns, creds->fsuid);
+
+ mf->gid = make_kgid(ns, creds->gid);
+ mf->egid = make_kgid(ns, creds->egid);
+ mf->sgid = make_kgid(ns, creds->sgid);
+ mf->fsgid = make_kgid(ns, creds->fsgid);
+
+ if ((creds->uid != (uid_t)-1 && !uid_valid(mf->uid)) ||
+ (creds->euid != (uid_t)-1 && !uid_valid(mf->euid)) ||
+ (creds->suid != (uid_t)-1 && !uid_valid(mf->suid)) ||
+ (creds->fsuid != (uid_t)-1 && !uid_valid(mf->fsuid)) ||
+ (creds->gid != (gid_t)-1 && !gid_valid(mf->gid)) ||
+ (creds->egid != (gid_t)-1 && !gid_valid(mf->egid)) ||
+ (creds->sgid != (gid_t)-1 && !gid_valid(mf->sgid)) ||
+ (creds->fsgid != (gid_t)-1 && !gid_valid(mf->fsgid)))
+ return -EINVAL;
+
+ mf->valid |= KDBUS_ATTACH_CREDS;
}
- if (pids && !(mp->collected & KDBUS_ATTACH_PIDS)) {
- mp->pid = get_pid(find_vpid(pids->tid));
- mp->tgid = get_pid(find_vpid(pids->pid));
- mp->ppid = get_pid(find_vpid(pids->ppid));
-
- if ((pids->tid != 0 && !mp->pid) ||
- (pids->pid != 0 && !mp->tgid) ||
- (pids->ppid != 0 && !mp->ppid)) {
- put_pid(mp->pid);
- put_pid(mp->tgid);
- put_pid(mp->ppid);
- mp->pid = NULL;
- mp->tgid = NULL;
- mp->ppid = NULL;
- ret = -EINVAL;
- goto exit_unlock;
+ if (pids) {
+ mf->pid = get_pid(find_vpid(pids->tid));
+ mf->tgid = get_pid(find_vpid(pids->pid));
+ mf->ppid = get_pid(find_vpid(pids->ppid));
+
+ if ((pids->tid != 0 && !mf->pid) ||
+ (pids->pid != 0 && !mf->tgid) ||
+ (pids->ppid != 0 && !mf->ppid)) {
+ put_pid(mf->pid);
+ put_pid(mf->tgid);
+ put_pid(mf->ppid);
+ mf->pid = NULL;
+ mf->tgid = NULL;
+ mf->ppid = NULL;
+ return -EINVAL;
}
- mp->valid |= KDBUS_ATTACH_PIDS;
- mp->collected |= KDBUS_ATTACH_PIDS;
+ mf->valid |= KDBUS_ATTACH_PIDS;
}
- if (seclabel && !(mp->collected & KDBUS_ATTACH_SECLABEL)) {
- mp->seclabel = kstrdup(seclabel, GFP_KERNEL);
- if (!mp->seclabel) {
- ret = -ENOMEM;
- goto exit_unlock;
- }
+ if (seclabel) {
+ mf->seclabel = kstrdup(seclabel, GFP_KERNEL);
+ if (!mf->seclabel)
+ return -ENOMEM;
- mp->valid |= KDBUS_ATTACH_SECLABEL;
- mp->collected |= KDBUS_ATTACH_SECLABEL;
+ mf->valid |= KDBUS_ATTACH_SECLABEL;
}
- ret = 0;
-
-exit_unlock:
- mutex_unlock(&mp->lock);
- return ret;
+ return 0;
}
/**
@@ -768,6 +783,7 @@ exit_unlock:
/*
* kdbus_meta_export_prepare() - Prepare metadata for export
* @mp: Process metadata, or NULL
+ * @mf: Fake metadata, or NULL
* @mc: Connection metadata, or NULL
* @mask: Pointer to mask of KDBUS_ATTACH_* flags to export
* @sz: Pointer to return the size needed by the metadata
@@ -783,6 +799,7 @@ exit_unlock:
* Return: 0 on success, negative error number otherwise.
*/
int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp,
+ struct kdbus_meta_fake *mf,
struct kdbus_meta_conn *mc,
u64 *mask, size_t *sz)
{
@@ -792,6 +809,12 @@ int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp,
u64 valid = 0;
int ret = 0;
+ if (WARN_ON(mf && mp))
+ mp = NULL;
+
+ if (mf)
+ valid |= mf->valid;
+
if (mp) {
mutex_lock(&mp->lock);
valid |= mp->valid;
@@ -811,10 +834,10 @@ int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp,
/* process metadata */
- if (mp && (*mask & KDBUS_ATTACH_CREDS))
+ if ((mp || mf) && (*mask & KDBUS_ATTACH_CREDS))
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds));
- if (mp && (*mask & KDBUS_ATTACH_PIDS))
+ if ((mp || mf) && (*mask & KDBUS_ATTACH_PIDS))
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids));
if (mp && (*mask & KDBUS_ATTACH_AUXGROUPS))
@@ -852,8 +875,9 @@ int kdbus_meta_export_prepare(struct kdbus_meta_proc *mp,
if (mp && (*mask & KDBUS_ATTACH_CAPS))
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps));
- if (mp && (*mask & KDBUS_ATTACH_SECLABEL))
- size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1);
+ if ((mp || mf) && (*mask & KDBUS_ATTACH_SECLABEL))
+ size += KDBUS_ITEM_SIZE(strlen(mp ? mp->seclabel
+ : mf->seclabel) + 1);
if (mp && (*mask & KDBUS_ATTACH_AUDIT))
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit));
@@ -966,6 +990,7 @@ static gid_t kdbus_from_kgid_keep(struct user_namespace *ns, kgid_t gid)
/**
* kdbus_meta_export() - export information from metadata into a slice
* @mp: Process metadata, or NULL
+ * @mf: Fake metadata, or NULL
* @mc: Connection metadata, or NULL
* @conn: Target connection to translate metadata into
* @mask: Mask of KDBUS_ATTACH_* flags to export
@@ -988,6 +1013,7 @@ static gid_t kdbus_from_kgid_keep(struct user_namespace *ns, kgid_t gid)
* Return: 0 on success, negative error number otherwise.
*/
int kdbus_meta_export(struct kdbus_meta_proc *mp,
+ struct kdbus_meta_fake *mf,
struct kdbus_meta_conn *mc,
struct kdbus_conn *conn,
u64 mask,
@@ -1007,6 +1033,9 @@ int kdbus_meta_export(struct kdbus_meta_proc *mp,
u64 size = 0;
int ret = 0;
+ if (WARN_ON(mf && mp))
+ mp = NULL;
+
hdr = &item_hdr[0];
if (mask == 0) {
@@ -1016,7 +1045,19 @@ int kdbus_meta_export(struct kdbus_meta_proc *mp,
/* process metadata */
- if (mp && (mask & KDBUS_ATTACH_CREDS)) {
+ if (mf && (mask & KDBUS_ATTACH_CREDS)) {
+ creds.uid = kdbus_from_kuid_keep(user_ns, mf->uid);
+ creds.euid = kdbus_from_kuid_keep(user_ns, mf->euid);
+ creds.suid = kdbus_from_kuid_keep(user_ns, mf->suid);
+ creds.fsuid = kdbus_from_kuid_keep(user_ns, mf->fsuid);
+ creds.gid = kdbus_from_kgid_keep(user_ns, mf->gid);
+ creds.egid = kdbus_from_kgid_keep(user_ns, mf->egid);
+ creds.sgid = kdbus_from_kgid_keep(user_ns, mf->sgid);
+ creds.fsgid = kdbus_from_kgid_keep(user_ns, mf->fsgid);
+
+ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, KDBUS_ITEM_CREDS,
+ &creds, sizeof(creds), &size);
+ } else if (mp && (mask & KDBUS_ATTACH_CREDS)) {
creds.uid = kdbus_from_kuid_keep(user_ns, mp->uid);
creds.euid = kdbus_from_kuid_keep(user_ns, mp->euid);
creds.suid = kdbus_from_kuid_keep(user_ns, mp->suid);
@@ -1030,7 +1071,14 @@ int kdbus_meta_export(struct kdbus_meta_proc *mp,
&creds, sizeof(creds), &size);
}
- if (mp && (mask & KDBUS_ATTACH_PIDS)) {
+ if (mf && (mask & KDBUS_ATTACH_PIDS)) {
+ pids.pid = pid_nr_ns(mf->tgid, conn->pid_ns);
+ pids.tid = pid_nr_ns(mf->pid, conn->pid_ns);
+ pids.ppid = pid_nr_ns(mf->ppid, conn->pid_ns);
+
+ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++, KDBUS_ITEM_PIDS,
+ &pids, sizeof(pids), &size);
+ } else if (mp && (mask & KDBUS_ATTACH_PIDS)) {
pids.pid = pid_nr_ns(mp->tgid, conn->pid_ns);
pids.tid = pid_nr_ns(mp->pid, conn->pid_ns);
pids.ppid = pid_nr_ns(mp->ppid, conn->pid_ns);
@@ -1124,7 +1172,11 @@ int kdbus_meta_export(struct kdbus_meta_proc *mp,
sizeof(caps), &size);
}
- if (mp && (mask & KDBUS_ATTACH_SECLABEL))
+ if (mf && (mask & KDBUS_ATTACH_SECLABEL))
+ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++,
+ KDBUS_ITEM_SECLABEL, mf->seclabel,
+ strlen(mf->seclabel) + 1, &size);
+ else if (mp && (mask & KDBUS_ATTACH_SECLABEL))
cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++,
KDBUS_ITEM_SECLABEL, mp->seclabel,
strlen(mp->seclabel) + 1, &size);