Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@bof
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bof/40b8e035f73c7d846ec0 to your computer and use it in GitHub Desktop.
Save bof/40b8e035f73c7d846ec0 to your computer and use it in GitHub Desktop.
shellshock mitigating kernel patch
--- linux-3.10.40/fs/binfmt_elf.c 2014-05-13 14:00:04.000000000 +0200
+++ linux-3.10.40-shellshock/fs/binfmt_elf.c 2014-09-30 08:40:06.616396236 +0200
@@ -307,11 +307,37 @@
current->mm->arg_end = current->mm->env_start = p;
while (envc-- > 0) {
size_t len;
+ size_t shock_len;
+ char *shock_p, shock[48], shock_comm[sizeof(current->comm)];
if (__put_user((elf_addr_t)p, envp++))
return -EFAULT;
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN)
return -EINVAL;
+ shock_len = len;
+ if (shock_len > sizeof(shock))
+ shock_len = sizeof(shock);
+ if (!copy_from_user(shock, (void __user *)p, shock_len)) {
+ shock[sizeof(shock)-1] = '\0';
+ for (shock_p = shock; *shock_p; shock_p++) {
+ if (shock_p[0] != '=') {
+ continue;
+ }
+ if ( shock_p[1] != '('
+ || shock_p[2] != ')'
+ || shock_p[3] != ' '
+ || shock_p[4] != '{') {
+ break;
+ }
+ envp--;
+ printk(KERN_ERR "shocked by '%.*s=...' from UID %u PID %u [%s] - ignoring...\n",
+ (int)(shock_p-shock), shock,
+ from_kuid_munged(cred->user_ns, cred->euid),
+ current->pid,
+ get_task_comm(shock_comm, current));
+ break;
+ }
+ }
p += len;
}
if (__put_user(0, envp))
@bof
Copy link
Author

bof commented Sep 26, 2014

Short explanation, should anybody read this:

The patch modifies the place where, during (ELF binary) exec, the envp array-of-pointers-to-environment-variables is created.

At some cost in performance, it copies down the first 63 bytes of each environment variable into kernel memory, then looks for the first '=' sign, and for the next two characters after that being "()" - the string that starts bash's magic "function importing" environment variables.

Any environment variable containing such a string, is dropped from the environment pointer array, which should be enough (and tests confirm that) for bash (or any other process) to not see it.

@bof
Copy link
Author

bof commented Sep 30, 2014

Third revision:

  • really break after first '=' in variable. the "break" was in the wrong place before...
  • fully match "() {" string that bash uses
  • also log UID

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment