diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 65c9609ec207..0f1138e16dbe 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -43,6 +43,7 @@ LSM_HOOK(int, 0, capset, struct cred *new, const struct cred *old,
const kernel_cap_t *permitted)
LSM_HOOK(int, 0, capable, const struct cred *cred, struct user_namespace *ns,
int cap, unsigned int opts)
+LSM_HOOK(int, 0, dma_buf_charge_task, const struct cred *from, const struct cred *to)
LSM_HOOK(int, 0, quotactl, int cmds, int type, int id, const struct super_block *sb)
LSM_HOOK(int, 0, quota_on, struct dentry *dentry)
LSM_HOOK(int, 0, syslog, int type)
diff --git a/include/linux/security.h b/include/linux/security.h
index 153e9043058f..89a35eb07b8c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -350,6 +350,7 @@ int security_capable(const struct cred *cred,
struct user_namespace *ns,
int cap,
unsigned int opts);
+int security_dma_buf_charge_task(const struct cred *from, const struct cred *to);
int security_quotactl(int cmds, int type, int id, const struct super_block *sb);
int security_quota_on(struct dentry *dentry);
int security_syslog(int type);
@@ -701,6 +702,12 @@ static inline int security_capable(const struct cred *cred,
return cap_capable(cred, ns, cap, opts);
}
+static inline int security_dma_buf_charge_task(const struct cred *from,
+ const struct cred *to)
+{
+ return 0;
+}
+
static inline int security_quotactl(int cmds, int type, int id,
const struct super_block *sb)
{diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f66254f52b99..ad195cfd1b5f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -59,6 +59,7 @@
#include <linux/lockdep.h>
#include <linux/resume_user_mode.h>
#include <linux/psi.h>
+#include <linux/security.h>
#include <linux/seq_buf.h>
#include <linux/sched/isolation.h>
#include <linux/kmemleak.h>
@@ -5672,11 +5673,13 @@ void mem_cgroup_flush_workqueue(void)
struct mem_cgroup *mem_cgroup_get_from_fd(int fd)
{
struct cgroup_subsys_state *css;
+ const struct cred *tcred;
struct mem_cgroup *memcg;
struct cgroup *cgrp;
struct task_struct *task;
struct mm_struct *mm;
unsigned int pidfd_flags;
+ int ret;
cgrp = cgroup_get_from_fd(fd);
if (!IS_ERR(cgrp)) {@@ -5698,6 +5701,14 @@ struct mem_cgroup *mem_cgroup_get_from_fd(int fd)
if (IS_ERR(task))
return ERR_CAST(task);
+ tcred = get_task_cred(task);
+ ret = security_dma_buf_charge_task(current_cred(), tcred);
+ put_cred(tcred);
+ if (ret) {
+ put_task_struct(task);
+ return ERR_PTR(ret);
+ }
+
mm = get_task_mm(task);
put_task_struct(task);
if (!mm)diff --git a/security/security.c b/security/security.c
index 2ee276ab15c5..4a16e4076aab 100644
--- a/security/security.c
+++ b/security/security.c
@@ -660,6 +660,22 @@ int security_capable(const struct cred *cred,
return call_int_hook(capable, cred, ns, cap, opts);
}
+/**
+ * security_dma_buf_charge_task() - Check if cross-cgroup dma-heap charging is allowed
+ * @from: credentials of the allocating process
+ * @to: credentials of the process to charge
+ *
+ * Check whether the process with credentials @from is allowed to allocate
+ * dma-heap memory and charge it to the cgroup of the process with credentials
+ * @to.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_dma_buf_charge_task(const struct cred *from, const struct cred *to)
+{
+ return call_int_hook(dma_buf_charge_task, from, to);
+}
+
/**
* security_quotactl() - Check if a quotactl() syscall is allowed for this fs
* @cmds: commands
--
2.55.0