return 0;
}
-static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp)
+static int kdbus_get_current_seclabel(char **pseclabel)
{
#ifdef CONFIG_SECURITY
+ char const *label;
char *ctx = NULL;
u32 sid, len;
int ret;
return (ret == -EOPNOTSUPP) ? 0 : ret;
}
- mp->seclabel = kstrdup(ctx, GFP_KERNEL);
+ label = kstrdup(ctx, GFP_KERNEL);
security_release_secctx(ctx, len);
- if (!mp->seclabel)
+ if (!label)
return -ENOMEM;
-
- mp->valid |= KDBUS_ATTACH_SECLABEL;
+ *pseclabel = label;
#endif
+ return 0;
+}
+static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp)
+{
+#ifdef CONFIG_SECURITY
+ char *label;
+ int ret;
+
+ ret = kdbus_get_current_seclabel(&label);
+ if (ret < 0)
+ return ret;
+ if (label) {
+ mp->valid |= KDBUS_ATTACH_SECLABEL;
+ mp->seclabel = label;
+ }
+#endif
return 0;
}
+void kdbus_meta_proc_mark_dynamic_seclabel(struct kdbus_meta_proc *mp)
+{
+#ifdef CONFIG_SECURITY
+ WARN_ON(mp->valid & KDBUS_ATTACH_SECLABEL);
+ WARN_ON(mp->seclabel);
+ mp->valid |= KDBUS_ATTACH_SECLABEL;
+#endif
+}
+
static void kdbus_meta_proc_collect_audit(struct kdbus_meta_proc *mp)
{
#ifdef CONFIG_AUDITSYSCALL
const char *exe_path;
};
-static size_t kdbus_meta_measure(struct kdbus_meta_staging *staging)
+static size_t kdbus_meta_measure(struct kdbus_meta_staging *staging, char const *seclabel)
{
const struct kdbus_meta_proc *mp = staging->mp;
const struct kdbus_meta_fake *mf = staging->mf;
if (mf && (mask & KDBUS_ATTACH_SECLABEL))
size += KDBUS_ITEM_SIZE(strlen(mf->seclabel) + 1);
else if (mp && (mask & KDBUS_ATTACH_SECLABEL))
- size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1);
+ size += KDBUS_ITEM_SIZE(strlen(seclabel ?: mp->seclabel) + 1);
if (mp && (mask & KDBUS_ATTACH_AUDIT))
size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit));
}
static size_t kdbus_meta_write(struct kdbus_meta_staging *staging, void *mem,
- size_t size)
+ size_t size, char const *seclabel)
{
struct user_namespace *user_ns = staging->conn->cred->user_ns;
struct pid_namespace *pid_ns = ns_of_pid(staging->conn->pid);
item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL,
strlen(staging->mf->seclabel) + 1,
staging->mf->seclabel);
- else if (staging->mp && (staging->mask & KDBUS_ATTACH_SECLABEL))
+ else if (staging->mp && (staging->mask & KDBUS_ATTACH_SECLABEL)) {
+ char const *label = seclabel ?: staging->mp->seclabel;
item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL,
- strlen(staging->mp->seclabel) + 1,
- staging->mp->seclabel);
+ strlen(label) + 1,
+ label);
+ }
if (staging->mp && (staging->mask & KDBUS_ATTACH_AUDIT)) {
item = kdbus_write_head(&items, KDBUS_ITEM_AUDIT,
struct kdbus_item *items = NULL;
size_t size = 0;
int ret;
+ char *seclabel = NULL;
if (WARN_ON(mf && mp))
mp = NULL;
if (mf)
staging.mask |= mf->valid;
if (mp) {
+ char const *mp_seclabel;
mutex_lock(&mp->lock);
staging.mask |= mp->valid;
+ mp_seclabel = mp->seclabel;
mutex_unlock(&mp->lock);
+ if (staging.mask & mask & KDBUS_ATTACH_SECLABEL && !mp_seclabel) {
+ /* dynamic seclabel */
+ ret = kdbus_get_current_seclabel(&seclabel);
+ if (ret < 0)
+ goto exit;
+ if (!seclabel)
+ staging.mask &= ~KDBUS_ATTACH_SECLABEL;
+ }
}
if (mc) {
mutex_lock(&mc->lock);
path_put(&p);
}
- size = kdbus_meta_measure(&staging);
+ size = kdbus_meta_measure(&staging, seclabel);
if (!size) { /* bail out if nothing to do */
ret = 0;
goto exit;
goto exit;
}
- size = kdbus_meta_write(&staging, items, size);
+ size = kdbus_meta_write(&staging, items, size, seclabel);
if (!size) {
kfree(items);
items = NULL;
ret = 0;
exit:
+ kfree(seclabel);
if (staging.exe)
free_page((unsigned long)staging.exe);
if (ret >= 0) {