diff -urN linux-2.4.20/Documentation/Configure.help linux-2.4.20/Documentation/Configure.help --- linux-2.4.20/Documentation/Configure.help 2002-11-28 18:53:08.000000000 -0500 +++ linux-2.4.20/Documentation/Configure.help 2003-02-12 23:36:37.000000000 -0500 @@ -2569,6 +2569,20 @@ If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. +stealth networking support +CONFIG_IP_NF_MATCH_STEALTH + Enabling this option will drop all syn packets coming to unserved tcp + ports as well as all packets coming to unserved udp ports. If you + are using your system to route any type of packets (ie. via NAT) + you should put this module at the end of your ruleset, since it will + drop packets that aren't going to ports that are listening on your + machine itself, it doesn't take into account that the packet might be + destined for someone on your internal network if you're using NAT for + instance. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + MAC address match support CONFIG_IP_NF_MATCH_MAC MAC matching allows you to match packets based on the source @@ -21427,6 +21441,813 @@ "Area6" will work for most boards. For ADX, select "Area5". +Grsecurity +CONFIG_GRKERNSEC + If you say Y here, you will be able to configure many features that + will enhance the security of your system. It is highly recommended + that you say Y here and read through the help for each option so + you fully understand the features and can evaluate their usefulness + for your machine. + +Additional security levels +CONFIG_GRKERNSEC_LOW + + Low additional security + ----------------------------------------------------------------------- + If you choose this option, several of the grsecurity options will + be enabled that will give you greater protection against a number + of attacks, while assuring that none of your software will have any + conflicts with the additional security measures. If you run a lot of + unusual software, or you are having problems with the higher security + levels, you should say Y here. With this option, the following features + are enabled: + + linking restrictions + fifo restrictions + random pids + enforcing nproc on execve() + restricted dmesg + random ip ids + enforced chdir("/") on chroot + + Medium additional security + ----------------------------------------------------------------------- + If you say Y here, several features in addition to those included in the + low additional security level will be enabled. These features provide + even more security to your system, though in rare cases they may + be incompatible with very old or poorly written software. If you + enable this option, make sure that your auth service (identd) is + running as gid 10 (usually group wheel). With this option the following + features (in addition to those provided in the low additional security + level) will be enabled: + + random tcp source ports + altered ping ids + failed fork logging + time change logging + signal logging + deny mounts in chroot + deny double chrooting + deny sysctl writes in chroot + deny mknod in chroot + deny access to abstract AF_UNIX sockets out of chroot + deny pivot_root in chroot + denied writes of /dev/kmem, /dev/mem, and /dev/port + /proc restrictions with special gid set to 10 (usually wheel) + address space layout randomization + + High additional security + ---------------------------------------------------------------------- + If you say Y here, many of the features of grsecurity will be enabled, + that will protect you against virtually all kinds of attacks against + your system. The much hightened security comes at a cost of an + increased chance of incompatabilities with rare software on your + machine. It is highly recommended that you view + and read about each option. Since + this security level enabled PaX, you should also view + and read about the PaX project. While + you are there, download chpax.c and run chpax -p on binaries that cause + problems with PaX. Also remember that since the /proc restrictions are + enabled, you must run your identd as group wheel (gid 10). + This security level enables the following features in addition to those + listed in the low and medium security levels: + + additional /proc restrictions + chmod restrictions in chroot + no signals, ptrace, or viewing processes outside of chroot + capability restrictions in chroot + deny fchdir out of chroot + priority restrictions in chroot + segmentation-based implementation of PaX + mprotect restrictions + removal of /proc//[maps|mem] + kernel stack randomization + mount/unmount/remount logging + + +Customized additional security +CONFIG_GRKERNSEC_CUSTOM + If you say Y here, you will be able to configure every grsecurity + option, which allows you to enable many more features that aren't + covered in the basic security levels. These additional features include + TPE, socket restrictions, and the sysctl system for grsecurity. It is + advised that you read through the help for each option to determine its + usefulness in your situation. + +Enforce non-executable pages +CONFIG_GRKERNSEC_PAX_NOEXEC + By design the IA-32 architecture does not allow for protecting + memory pages against execution, i.e. if a page is readable (such + as the stack or heap) it is also executable. There is a well + known exploit technique that makes use of this fact and a common + programming mistake where an attacker can introduce executable + code of his choice somewhere in the attacked program's memory + (typically the stack or the heap) and then execute it. If the + attacked program was running with different (typically higher) + privileges than that of the attacker, then he can elevate his + own privilege level (e.g. get a root shell, write to files for + which he does not have write access to, etc). + + There are two implementations provided here, each with its own + impact on performance and usability. You should enable at least + one of them to enforce the non-executable flag on memory pages + thereby making it harder to execute 'foreign' code in a program. + + This will also break programs that rely on the old behaviour and + expect that dynamically allocated memory via the malloc() family + of functions is executable (which it is not). Notable examples + are the XFree86 4.x server, the java runtime and wine. + + NOTE: you can use the 'chpax' utility to enable/disable this + feature on a per file basis. chpax is available at + + +Paging based non-executable pages +CONFIG_GRKERNSEC_PAX_PAGEEXEC + This implementation is based on the paging feature of the CPU + and has a variable performance impact on applications depending + on their memory usage pattern. You should carefully evaluate + your applications before using this feature in production. + +Segmentation based non-executable pages +CONFIG_GRKERNSEC_PAX_SEGMEXEC + This implementation is based on the segmentation feature of the + CPU and has little performance impact, however applications will + be limited to a 1.5 GB address space instead of the normal 3 GB. + +Emulate trampolines +CONFIG_GRKERNSEC_PAX_EMUTRAMP + There are some programs and libraries that for one reason or + another attempt to execute special small code snippets from + non-executable memory pages. Most notable examples are the + signal handler return code generated by the kernel itself and + the GCC trampolines. + + If you enabled CONFIG_GRKERNSEC_PAX_PAGEEXEC or + CONFIG_GRKERNSEC_PAX_SEGMEXEC then such programs will no longer + work under your kernel. + + As a remedy you can say Y here and use the 'chpax' utility to + enable trampoline emulation for the affected programs yet still + have the protection provided by the non-executable pages. + + Alternatively you can say N here and use the 'chpax' utility + to disable CONFIG_GRKERNSEC_PAX_PAGEEXEC and + CONFIG_GRKERNSEC_PAX_SEGMEXEC for the affected files. + + NOTE: enabling this feature *may* open up a loophole in the + protection provided by non-executable pages that an attacker + could abuse. Therefore the best solution is to not have any + files on your system that would require this option. This can + be achieved by not using libc5 (which relies on the kernel + signal handler return code) and not using or rewriting programs + that make use of the nested function implementation of GCC. + Skilled users can just fix GCC itself so that it implements + nested function calls in a way that does not interfere with PaX. + +Automatically emulate sigreturn trampolines +CONFIG_GRKERNSEC_PAX_EMUSIGRT + Enabling this option will have the kernel automatically detect + and emulate signal return trampolines executing on the stack + that would otherwise lead to task termination. + + This solution is intended as a temporary one for users with + legacy versions of libc (libc5, glibc 2.0, uClibc, Modula-3 + runtime, etc) or executables linked to such, basically everything + that does not specify its own SA_RESTORER function in normal + executable memory like glibc 2.1+ does. + + NOTE: this feature cannot be disabled on a per executable basis + and since it *does* open up a loophole in the protection provided + by non-executable pages, the best solution is to not have any + files on your system that would require this option. + +Restrict mprotect() +CONFIG_GRKERNSEC_PAX_MPROTECT + Enabling this option will prevent programs from + - changing the executable status of memory pages that were + not originally created as executable, + - making read-only executable pages writable again, + - creating executable pages from anonymous memory. + + You should say Y here to complete the protection provided by + the enforcement of non-executable pages. + + NOTE: you can use the 'chpax' utility to control this + feature on a per file basis. chpax is available at + + +Disallow ELF text relocations +CONFIG_GRKERNSEC_PAX_NOELFRELOCS + Non-executable pages and mprotect() restrictions are effective + in preventing the introduction of new executable code into an + attacked task's address space. There remain only two venues + for this kind of attack: if the attacker can execute already + existing code in the attacked task then he can either have it + create and mmap() a file containing his code or have it mmap() + an already existing ELF library that does not have position + independent code in it and use mprotect() on it to make it + writable and copy his code there. While protecting against + the former approach is beyond PaX, the latter can be prevented + by having only PIC ELF libraries on one's system (which do not + need to relocate their code). If you are sure this is your case, + then enable this option otherwise be careful as you may not even + be able to boot or log on your system (for example, some PAM + modules are erroneously compiled as non-PIC by default). + + NOTE: if you are using dymamic ELF executables (as suggested + when using ASLR) then you must have made sure that you linked + your files using the PIC version of crt1 (the et_dyn.zip package + referenced there has already been updated to support this). + +Address Space Layout Randomization +CONFIG_GRKERNSEC_PAX_ASLR + Many if not most exploit techniques rely on the knowledge of + certain addresses in the attacked program. The following options + will allow the kernel to apply a certain amount of randomization + to specific parts of the program thereby forcing an attacker to + guess them in most cases. Any failed guess will most likely crash + the attacked program which allows the kernel to detect such attempts + and react on them. PaX itself provides no reaction mechanisms, + instead it is strongly encouraged that you make use of grsecurity's + built-in crash detection features or develop one yourself. + + By saying Y here you can choose to randomize the following areas: + - top of the task's kernel stack + - top of the task's userland stack + - base address for mmap() requests that do not specify one + (this includes all libraries) + - base address of the main executable + + It is strongly recommended to say Y here as address space layout + randomization has negligible impact on performance yet it provides + a very effective protection. + + NOTE: you can use the 'chpax' utility to control most of these features + on a per file basis. + +Randomize kernel stack base +CONFIG_GRKERNSEC_PAX_RANDKSTACK + By saying Y here the kernel will randomize every task's kernel + stack on every system call. This will not only force an attacker + to guess it but also prevent him from making use of possible + leaked information about it. + + Since the kernel stack is a rather scarce resource, randomization + may cause unexpected stack overflows, therefore you should very + carefully test your system. Note that once enabled in the kernel + configuration, this feature cannot be disabled on a per file basis. + +Randomize user stack base +CONFIG_GRKERNSEC_PAX_RANDUSTACK + By saying Y here the kernel will randomize every task's userland + stack. The randomization is done in two steps where the second + one may apply a big amount of shift to the top of the stack and + cause problems for programs that want to use lots of memory (more + than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is). + For this reason the second step can be controlled by 'chpax' on + a per file basis. + +Randomize ET_EXEC base +CONFIG_GRKERNSEC_PAX_RANDEXEC + By saying Y here the kernel will randomize the base address of normal + ET_EXEC ELF executables as well. This is accomplished by mapping the + executable in memory in a special way which also allows for detecting + attackers who attempt to execute its code for their purposes. Since + this special mapping causes performance degradation and the attack + detection may create false alarms as well, you should carefully test + your executables when this feature is enabled. + + This solution is intended only as a temporary one until you relink + your programs as a dynamic ELF file. + + NOTE: you can use the 'chpax' utility to control this feature + on a per file basis. + +Randomize mmap() base +CONFIG_GRKERNSEC_PAX_RANDMMAP + By saying Y here the kernel will use a randomized base address for + mmap() requests that do not specify one themselves. As a result + all dynamically loaded libraries will appear at random addresses + and therefore be harder to exploit by a technique where an attacker + attempts to execute library code for his purposes (e.g. spawn a + shell from an exploited program that is running at an elevated + privilege level). + + Furthermore, if a program is relinked as a dynamic ELF file, its + base address will be randomized as well, completing the full + randomization of the address space layout. Attacking such programs + becomes a guess game. You can find an example of doing this at + and practical samples at + . + + NOTE: you can use the 'chpax' utility to control this feature + on a per file basis. + +Deny writing to /dev/kmem, /dev/mem, and /dev/port +CONFIG_GRKERNSEC_KMEM + If you say Y here, /dev/kmem and /dev/mem won't be allowed to + be written to via mmap or otherwise to modify the running kernel. + /dev/port will also not be allowed to be opened. If you have module + support disabled, enabling this will close up four ways that are + currently used to insert malicious code into the running kernel. + Even with all these features enabled, we still highly recommend that + you use the ACL system, as it is still possible for an attacker to + modify the running kernel through privileged I/O granted by ioperm/iopl. + If you are not using XFree86, you may be able to stop this additional + case by enabling the 'Disable privileged I/O' option. Though nothing + legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem, + but only to video memory, which is the only writing we allow in this + case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will + not be allowed to mprotect it with PROT_WRITE later. + Enabling this feature could make certain apps like VMWare stop working, + as they need to write to other locations in /dev/mem. + It is highly recommended that you say Y here. + +Disable privileged I/O +CONFIG_GRKERNSEC_IO + If you say Y here, all ioperm and iopl calls will return an error. + Ioperm and iopl can be used to modify the running kernel. + Unfortunately, some problems need this access to operate properly, + the most notable of which are XFree86 and hwclock. hwclock can be + remedied by having RTC support in the kernel, so CONFIG_RTC is + enabled if this option is enabled, to ensure that hwclock operates + correctly. XFree86 still will not operate correctly with this option + enabled, so DO NOT CHOOSE Y IF YOU USE XFree86. If you use XFree86 + and you still want to protect your kernel against modification, + use the ACL system. + +Proc Restrictions +CONFIG_GRKERNSEC_PROC + If you say Y here, the permissions of the /proc filesystem + will be altered to enhance system security and privacy. Depending + upon the options you choose, you can either restrict users to see + only the processes they themselves run, or choose a group that can + view all processes and files normally restricted to root if you choose + the "restrict to user only" option. NOTE: If you're running identd as + a non-root user, you will have to run it as the group you specify here. + +Restrict /proc to user only +CONFIG_GRKERNSEC_PROC_USER + If you say Y here, non-root users will only be able to view their own + processes, and restricts them from viewing network-related information, + and viewing kernel symbol and module information. + +Restrict /proc to user and group +CONFIG_GRKERNSEC_PROC_USERGROUP + If you say Y here, you will be able to select a group that will be + able to view all processes, network-related information, and + kernel and symbol information. This option is useful if you want + to run identd as a non-root user. + +Remove addresses from /proc/pid/maps +CONFIG_GRKERNSEC_PROC_MEMMAP + If you say Y here, the /proc//maps file will + give no information about the addresses of its mappings if + PaX features that rely on random addresses are enabled on the task. + If you use PaX it is greatly recommended that you say Y here as it + closes up a hole that makes the full ASLR useless for suid + binaries. + +Additional proc restrictions +CONFIG_GRKERNSEC_PROC_ADD + If you say Y here, additional restrictions will be placed on + /proc that keep normal users from viewing cpu and device information. + +Dmesg(8) Restriction +CONFIG_GRKERNSEC_DMESG + If you say Y here, non-root users will not be able to use dmesg(8) + to view up to the last 4kb of messages in the kernel's log buffer. + If the sysctl option is enabled, a sysctl option with name "dmesg" is + created. + +Linking restrictions +CONFIG_GRKERNSEC_LINK + If you say Y here, /tmp race exploits will be prevented, since users + will no longer be able to follow symlinks owned by other users in + world-writeable +t directories (i.e. /tmp), unless the owner of the + symlink is the owner of the directory. users will also not be + able to hardlink to files they do not own. If the sysctl option is + enabled, a sysctl option with name "linking_restrictions" is created. + +FIFO restrictions +CONFIG_GRKERNSEC_FIFO + If you say Y here, users will not be able to write to FIFOs they don't + own in world-writeable +t directories (i.e. /tmp), unless the owner of + the FIFO is the same owner of the directory it's held in. If the sysctl + option is enabled, a sysctl option with name "fifo_restrictions" is + created. + +Exec process limiting +CONFIG_GRKERNSEC_EXECVE + If you say Y here, users with a resource limit on processes will + have the value checked during execve() calls. The current system + only checks the system limit during fork() calls. If the sysctl option + is enabled, a sysctl option with name "execve_limiting" is created. + +Single group for auditing +CONFIG_GRKERNSEC_AUDIT_GROUP + If you say Y here, the exec, chdir, (un)mount, and ipc logging features + will only operate on a group you specify. This option is recommended + if you only want to watch certain users instead of having a large + amount of logs from the entire system. If the sysctl option is enabled, + a sysctl option with name "audit_group" is created. + +GID for auditing +CONFIG_GRKERNSEC_AUDIT_GID + Here you can choose the GID that will be the target of kernel auditing. + Remember to add the users you want to log to the GID specified here. + If the sysctl option is enabled, whatever you choose here won't matter. + You'll have to specify the GID in your bootup script by echoing the GID + to the proper /proc entry. View the help on the sysctl option for more + information. If the sysctl option is enabled, a sysctl option with name + "audit_gid" is created. + +Chdir logging +CONFIG_GRKERNSEC_AUDIT_CHDIR + If you say Y here, all chdir() calls will be logged. If the sysctl + option is enabled, a sysctl option with name "audit_chdir" is created. + +(Un)Mount logging +CONFIG_GRKERNSEC_AUDIT_MOUNT + If you say Y here, all mounts and unmounts will be logged. If the + sysctl option is enabled, a sysctl option with name "audit_mount" is + created. + +IPC logging +CONFIG_GRKERNSEC_AUDIT_IPC + If you say Y here, creation and removal of message queues, semaphores, + and shared memory will be logged. If the sysctl option is enabled, a + sysctl option with name "audit_ipc" is created. + +Exec logging +CONFIG_GRKERNSEC_EXECLOG + If you say Y here, all execve() calls will be logged (since the + other exec*() calls are frontends to execve(), all execution + will be logged). Useful for shell-servers that like to keep track + of their users. If the sysctl option is enabled, a sysctl option with + name "exec_logging" is created. + WARNING: This option when enabled will produce a LOT of logs, especially + on an active system. + +Resource logging +CONFIG_GRKERNSEC_RESLOG + If you say Y here, all attempts to overstep resource limits will + be logged with the resource name, the requested size, and the current + limit. It is highly recommended that you say Y here. + +Signal logging +CONFIG_GRKERNSEC_SIGNAL + If you say Y here, certain important signals will be logged, such as + SIGSEGV, which will as a result inform you of when a error in a program + occurred, which in some cases could mean a possible exploit attempt. + If the sysctl option is enabled, a sysctl option with name + "signal_logging" is created. + +Fork failure logging +CONFIG_GRKERNSEC_FORKFAIL + If you say Y here, all failed fork() attempts will be logged. + This could suggest a fork bomb, or someone attempting to overstep + their process limit. If the sysctl option is enabled, a sysctl option + with name "forkfail_logging" is created. + +Time change logging +CONFIG_GRKERNSEC_TIME + If you say Y here, any changes of the system clock will be logged. + If the sysctl option is enabled, a sysctl option with name + "timechange_logging" is created. + +Chroot jail restrictions +CONFIG_GRKERNSEC_CHROOT + If you say Y here, you will be able to choose several options that will + make breaking out of a chrooted jail much more difficult. If you + encounter no software incompatibilities with the following options, it + is recommended that you enable each one. + +Deny access to abstract AF_UNIX sockets out of chroot +CONFIG_GRKERNSEC_CHROOT_UNIX + If you say Y here, processes inside a chroot will not be able to + connect to abstract (meaning not belonging to a filesystem) Unix + domain sockets that were bound outside of a chroot. It is recommended + that you say Y here. If the sysctl option is enabled, a sysctl option + with name "chroot_deny_unix" is created. + +Deny shmat() out of chroot +CONFIG_GRKERNSEC_CHROOT_SHMAT + If you say Y here, processes inside a chroot will not be able to attach + to shared memory segments that were created outside of the chroot jail. + It is recommended that you say Y here. If the sysctl option is enabled, + a sysctl option with name "chroot_deny_shmat" is created. + +Protect outside processes +CONFIG_GRKERNSEC_CHROOT_FINDTASK + If you say Y here, processes inside a chroot will not be able to + kill, send signals with fcntl, ptrace, capget, setpgid, getpgid, + getsid, or view any process outside of the chroot. If the sysctl + option is enabled, a sysctl option with name "chroot_findtask" is + created. + +Deny mounts in chroot +CONFIG_GRKERNSEC_CHROOT_MOUNT + If you say Y here, processes inside a chroot will not be able to + mount or remount filesystems. If the sysctl option is enabled, a + sysctl option with name "chroot_deny_mount" is created. + +Deny pivot_root in chroot +CONFIG_GRKERNSEC_CHROOT_PIVOT + If you say Y here, processes inside a chroot will not be able to use + a function called pivot_root() that was introduced in Linux 2.3.41. It + works similar to chroot in that it changes the root filesystem. This + function could be misused in a chrooted process to attempt to break out + of the chroot, and therefore should not be allowed. If the sysctl + option is enabled, a sysctl option with name "chroot_deny_pivot" is + created. + +Deny double-chroots +CONFIG_GRKERNSEC_CHROOT_DOUBLE + If you say Y here, processes inside a chroot will not be able to chroot + again. This is a widely used method of breaking out of a chroot jail + and should not be allowed. If the sysctl option is enabled, a sysctl + option with name "chroot_deny_chroot" is created. + +Deny fchdir outside of chroot +CONFIG_GRKERNSEC_CHROOT_FCHDIR + If you say Y here, a well-known method of breaking chroots by fchdir'ing + to a file descriptor of the chrooting process that points to a directory + outside the filesystem will be stopped. If the sysctl option + is enabled, a sysctl option with name "chroot_deny_fchdir" is created. + +Enforce chdir("/") on all chroots +CONFIG_GRKERNSEC_CHROOT_CHDIR + If you say Y here, the current working directory of all newly-chrooted + applications will be set to the the root directory of the chroot. + The man page on chroot(2) states: + Note that this call does not change the current working + directory, so that `.' can be outside the tree rooted at + `/'. In particular, the super-user can escape from a + `chroot jail' by doing `mkdir foo; chroot foo; cd ..'. + + It is recommended that you say Y here, since it's not known to break + any software. If the sysctl option is enabled, a sysctl option with + name "chroot_enforce_chdir" is created. + +Deny (f)chmod +s in chroot +CONFIG_GRKERNSEC_CHROOT_CHMOD + If you say Y here, processes inside a chroot will not be able to chmod + or fchmod files to make them have suid or sgid bits. This protects + against another published method of breaking a chroot. If the sysctl + option is enabled, a sysctl option with name "chroot_deny_chmod" is + created. + +Deny mknod in chroot +CONFIG_GRKERNSEC_CHROOT_MKNOD + If you say Y here, processes inside a chroot will not be allowed to + mknod. The problem with using mknod inside a chroot is that it + would allow an attacker to create a device entry that is the same + as one on the physical root of your system, which could range from + anyhing from the console device to a device for your harddrive (which + they could then use to wipe the drive or steal data). It is recommended + that you say Y here, unless you run into software incompatibilities. + If the sysctl option is enabled, a sysctl option with name + "chroot_deny_mknod" is created. + +Restrict priority changes in chroot +CONFIG_GRKERNSEC_CHROOT_NICE + If you say Y here, processes inside a chroot will not be able to raise + the priority of processes in the chroot, or alter the priority of + processes outside the chroot. This provides more security than simply + removing CAP_SYS_NICE from the process' capability set. If the + sysctl option is enabled, a sysctl option with name "chroot_restrict_nice" + is created. + +Log all execs within chroot +CONFIG_GRKERNSEC_CHROOT_EXECLOG + If you say Y here, all executions inside a chroot jail will be logged + to syslog. This can cause a large amount of logs if certain + applications (eg. djb's daemontools) are installed on the system, and + is therefore left as an option. If the sysctl option is enabled, a + sysctl option with name "chroot_execlog" is created. + +Deny sysctl writes in chroot +CONFIG_GRKERNSEC_CHROOT_SYSCTL + If you say Y here, an attacker in a chroot will not be able to + write to sysctl entries, either by sysctl(2) or through a /proc + interface. It is strongly recommended that you say Y here. If the + sysctl option is enabled, a sysctl option with name + "chroot_deny_sysctl" is created. + +Chroot jail capability restrictions +CONFIG_GRKERNSEC_CHROOT_CAPS + If you say Y here, the capabilities on all root processes within a + chroot jail will be lowered to stop module insertion, raw i/o, + system and net admin tasks, rebooting the system, modifying immutable + files, modifying IPC owned by another, and changing the system time. + This is left an option because it can break some apps. Disable this + if your chrooted apps are having problems performing those kinds of + tasks. If the sysctl option is enabled, a sysctl option with + name "chroot_caps" is created. + +Trusted path execution +CONFIG_GRKERNSEC_TPE + If you say Y here, you will be able to choose a gid to add to the + supplementary groups of users you want to mark as "untrusted." + These users will not be able to execute any files that are not in + root-owned directories writeable only by root. If the sysctl option + is enabled, a sysctl option with name "tpe" is created. + +Group for trusted path execution +CONFIG_GRKERNSEC_TPE_GID + Here you can choose the GID to enable trusted path protection for. + Remember to add the users you want protection enabled for to the GID + specified here. If the sysctl option is enabled, whatever you choose + here won't matter. You'll have to specify the GID in your bootup + script by echoing the GID to the proper /proc entry. View the help + on the sysctl option for more information. If the sysctl option is + enabled, a sysctl option with name "tpe_gid" is created. + +Partially restrict non-root users +CONFIG_GRKERNSEC_TPE_ALL + If you say Y here, All non-root users other than the ones in the + group specified in the main TPE option will only be allowed to + execute files in directories they own that are not group or + world-writeable, or in directories owned by root and writeable only by + root. If the sysctl option is enabled, a sysctl option with name + "tpe_restrict_all" is created. + +Randomized PIDs +CONFIG_GRKERNSEC_RANDPID + If you say Y here, all PIDs created on the system will be + pseudo-randomly generated. This is extremely effective along + with the /proc restrictions to disallow an attacker from guessing + pids of daemons, etc. PIDs are also used in some cases as part + of a naming system for temporary files, so this option would keep + those filenames from being predicted as well. We also use code + to make sure that PID numbers aren't reused too soon. If the sysctl + option is enabled, a sysctl option with name "rand_pids" is created. + +Larger entropy pools +CONFIG_GRKERNSEC_RANDNET + If you say Y here, the entropy pools used for many features of Linux + and grsecurity will be doubled in size. Since several grsecurity + features use additional randomness, it is recommended that you say Y + here. Saying Y here has a similar effect as modifying + /proc/sys/kernel/random/poolsize. + +Truly random TCP ISN selection +CONFIG_GRKERNSEC_RANDISN + If you say Y here, Linux's default selection of TCP Initial Sequence + Numbers (ISNs) will be replaced with that of OpenBSD. Linux uses + an MD4 hash based on the connection plus a time value to create the + ISN, while OpenBSD's selection is random. If the sysctl option is + enabled, a sysctl option with name "rand_isns" is created. + +Randomized IP IDs +CONFIG_GRKERNSEC_RANDID + If you say Y here, all the id field on all outgoing packets + will be randomized. This hinders os fingerprinters and + keeps your machine from being used as a bounce for an untraceable + portscan. Ids are used for fragmented packets, fragments belonging + to the same packet have the same id. By default linux only + increments the id value on each packet sent to an individual host. + We use a port of the OpenBSD random ip id code to achieve the + randomness, while keeping the possibility of id duplicates to + near none. If the sysctl option is enabled, a sysctl option with name + "rand_ip_ids" is created. + +Randomized TCP source ports +CONFIG_GRKERNSEC_RANDSRC + If you say Y here, situations where a source port is generated on the + fly for the TCP protocol (ie. with connect() ) will be altered so that + the source port is generated at random, instead of a simple incrementing + algorithm. If the sysctl option is enabled, a sysctl option with name + "rand_tcp_src_ports" is created. + +Randomized RPC XIDs +CONFIG_GRKERNSEC_RANDRPC + If you say Y here, the method of determining XIDs for RPC requests will + be randomized, instead of using linux's default behavior of simply + incrementing the XID. If you want your RPC connections to be more + secure, say Y here. If the sysctl option is enabled, a sysctl option + with name "rand_rpc" is created. + +Altered Ping IDs +CONFIG_GRKERNSEC_RANDPING + If you say Y here, the way Linux handles echo replies will be changed + so that the reply uses an ID equal to the ID of the echo request. + This will help in confusing OS detection. If the sysctl option is + enabled, a sysctl option with name "altered_pings" is created. + +Socket restrictions +CONFIG_GRKERNSEC_SOCKET + If you say Y here, you will be able to choose from several options. + If you assign a GID on your system and add it to the supplementary + groups of users you want to restrict socket access to, this patch + will perform up to three things, based on the option(s) you choose. + +Deny all socket access +CONFIG_GRKERNSEC_SOCKET_ALL + If you say Y here, you will be able to choose a GID of whose users will + be unable to connect to other hosts from your machine or run server + applications from your machine. If the sysctl option is enabled, a + sysctl option with name "socket_all" is created. + +Group for disabled socket access +CONFIG_GRKERNSEC_SOCKET_ALL_GID + Here you can choose the GID to disable socket access for. Remember to + add the users you want socket access disabled for to the GID + specified here. If the sysctl option is enabled, whatever you choose + here won't matter. You'll have to specify the GID in your bootup + script by echoing the GID to the proper /proc entry. View the help + on the sysctl option for more information. If the sysctl option is + enabled, a sysctl option with name "socket_all_gid" is created. + +Deny all client socket access +CONFIG_GRKERNSEC_SOCKET_CLIENT + If you say Y here, you will be able to choose a GID of whose users will + be unable to connect to other hosts from your machine, but will be + able to run servers. If this option is enabled, all users in the group + you specify will have to use passive mode when initiating ftp transfers + from the shell on your machine. If the sysctl option is enabled, a + sysctl option with name "socket_client" is created. + +Group for disabled client socket access +CONFIG_GRKERNSEC_SOCKET_CLIENT_GID + Here you can choose the GID to disable client socket access for. + Remember to add the users you want client socket access disabled for to + the GID specified here. If the sysctl option is enabled, whatever you + choose here won't matter. You'll have to specify the GID in your bootup + script by echoing the GID to the proper /proc entry. View the help + on the sysctl option for more information. If the sysctl option is + enabled, a sysctl option with name "socket_client_gid" is created. + +Deny all server socket access +CONFIG_GRKERNSEC_SOCKET_SERVER + If you say Y here, you will be able to choose a GID of whose users will + be unable to run server applications from your machine. If the sysctl + option is enabled, a sysctl option with name "socket_server" is created. + +Group for disabled server socket access +CONFIG_GRKERNSEC_SOCKET_SERVER_GID + Here you can choose the GID to disable server socket access for. + Remember to add the users you want server socket access disabled for to + the GID specified here. If the sysctl option is enabled, whatever you + choose here won't matter. You'll have to specify the GID in your bootup + script by echoing the GID to the proper /proc entry. View the help + on the sysctl option for more information. If the sysctl option is + enabled, a sysctl option with name "socket_server_gid" is created. + +Sysctl support +CONFIG_GRKERNSEC_SYSCTL + If you say Y here, you will be able to change the options that + grsecurity runs with at bootup, without having to recompile your + kernel. You can echo values to files in /proc/sys/kernel/grsecurity + to enable (1) or disable (0) various features. All the sysctl entries + are mutable until the "grsec_lock" entry is set to a non-zero value. + All features are disabled by default. Please note that this option could + reduce the effectiveness of the added security of this patch if an ACL + system is not put in place. Your init scripts should be read-only, and + root should not have access to adding modules or performing raw i/o + operations. All options should be set at startup, and the grsec_lock + entry should be set to a non-zero value after all the options are set. + *THIS IS EXTREMELY IMPORTANT* + +Number of burst messages +CONFIG_GRKERNSEC_FLOODBURST + This option allows you to choose the maximum number of messages allowed + within the flood time interval you chose in a separate option. The + default should be suitable for most people, however if you find that + many of your logs are being interpreted as flooding, you may want to + raise this value. + +Seconds in between log messages +CONFIG_GRKERNSEC_FLOODTIME + This option allows you to enforce the number of seconds between + grsecurity log messages. The default should be suitable for most + people, however, if you choose to change it, choose a value small enough + to allow informative logs to be produced, but large enough to + prevent flooding. + +Hide kernel processes +CONFIG_GRKERNSEC_ACL_HIDEKERN + If you say Y here, when the ACL system is enabled via gradm -E, + an additional ACL will be passed to the kernel that hides all kernel + processes. These processes will only be viewable by the authenticated + admin, or processes that have viewing access set. + +Maximum tries before password lockout +CONFIG_GRKERNSEC_ACL_MAXTRIES + This option enforces the maximum number of times a user can attempt + to authorize themselves with the grsecurity ACL system before being + denied the ability to attempt authorization again for a specified time. + The lower the number, the harder it will be to brute-force a password. + +Time to wait after max password tries, in seconds +CONFIG_GRKERNSEC_ACL_TIMEOUT + This option specifies the time the user must wait after attempting to + authorize to the ACL system with the maximum number of invalid + passwords. The higher the number, the harder it will be to brute-force + a password. + Disable data cache CONFIG_DCACHE_DISABLE This option allows you to run the kernel with data cache disabled. diff -urN linux-2.4.20/Makefile linux-2.4.20/Makefile --- linux-2.4.20/Makefile 2002-11-28 18:53:16.000000000 -0500 +++ linux-2.4.20/Makefile 2003-02-12 23:36:37.000000000 -0500 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 20 -EXTRAVERSION = +EXTRAVERSION = -grsec KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -123,9 +123,10 @@ CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o NETWORKS =net/network.o +GRSECURITY =grsecurity/grsec.o LIBS =$(TOPDIR)/lib/lib.a -SUBDIRS =kernel drivers mm fs net ipc lib +SUBDIRS =kernel drivers mm fs net ipc lib grsecurity DRIVERS-n := DRIVERS-y := @@ -265,7 +266,7 @@ export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL -export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS +export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS GRSECURITY .S.s: $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $< @@ -284,6 +285,7 @@ $(CORE_FILES) \ $(DRIVERS) \ $(NETWORKS) \ + $(GRSECURITY) \ $(LIBS) \ --end-group \ -o vmlinux diff -urN linux-2.4.20/arch/alpha/config.in linux-2.4.20/arch/alpha/config.in --- linux-2.4.20/arch/alpha/config.in 2002-11-28 18:53:08.000000000 -0500 +++ linux-2.4.20/arch/alpha/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -425,3 +425,12 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -urN linux-2.4.20/arch/alpha/kernel/osf_sys.c linux-2.4.20/arch/alpha/kernel/osf_sys.c --- linux-2.4.20/arch/alpha/kernel/osf_sys.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20/arch/alpha/kernel/osf_sys.c 2003-02-12 23:36:37.000000000 -0500 @@ -240,6 +240,13 @@ if (!file) goto out; } + + if(gr_handle_mmap(file, prot)) { + fput(file); + ret = -EACCES; + goto out; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); ret = do_mmap(file, addr, len, prot, flags, off); diff -urN linux-2.4.20/arch/alpha/kernel/ptrace.c linux-2.4.20/arch/alpha/kernel/ptrace.c --- linux-2.4.20/arch/alpha/kernel/ptrace.c 2001-09-18 20:03:51.000000000 -0400 +++ linux-2.4.20/arch/alpha/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -273,6 +274,10 @@ read_unlock(&tasklist_lock); if (!child) goto out_notsk; + + if(gr_handle_ptrace(child, request)) + goto out; + if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out; diff -urN linux-2.4.20/arch/arm/config.in linux-2.4.20/arch/arm/config.in --- linux-2.4.20/arch/arm/config.in 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/arm/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -657,3 +657,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/cris/config.in linux-2.4.20/arch/cris/config.in --- linux-2.4.20/arch/cris/config.in 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/cris/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -258,3 +258,12 @@ source lib/Config.in endmenu + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -urN linux-2.4.20/arch/i386/config.in linux-2.4.20/arch/i386/config.in --- linux-2.4.20/arch/i386/config.in 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/i386/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -456,3 +456,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/i386/kernel/apm.c linux-2.4.20/arch/i386/kernel/apm.c --- linux-2.4.20/arch/i386/kernel/apm.c 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/i386/kernel/apm.c 2003-02-12 23:36:37.000000000 -0500 @@ -1923,6 +1923,12 @@ __va((unsigned long)0x40 << 4)); _set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4)); +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + set_base(gdt2[APM_40 >> 3], + __va((unsigned long)0x40 << 4)); + _set_limit((char *)&gdt2[APM_40 >> 3], 4095 - (0x40 << 4)); +#endif + apm_bios_entry.offset = apm_info.bios.offset; apm_bios_entry.segment = APM_CS; set_base(gdt[APM_CS >> 3], @@ -1931,6 +1937,16 @@ __va((unsigned long)apm_info.bios.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + set_base(gdt2[APM_CS >> 3], + __va((unsigned long)apm_info.bios.cseg << 4)); + set_base(gdt2[APM_CS_16 >> 3], + __va((unsigned long)apm_info.bios.cseg_16 << 4)); + set_base(gdt2[APM_DS >> 3], + __va((unsigned long)apm_info.bios.dseg << 4)); +#endif + #ifndef APM_RELAX_SEGMENTS if (apm_info.bios.version == 0x100) { #endif @@ -1940,6 +1956,13 @@ _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); /* For the DEC Hinote Ultra CT475 (and others?) */ _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + _set_limit((char *)&gdt2[APM_CS >> 3], 64 * 1024 - 1); + _set_limit((char *)&gdt2[APM_CS_16 >> 3], 64 * 1024 - 1); + _set_limit((char *)&gdt2[APM_DS >> 3], 64 * 1024 - 1); +#endif + #ifndef APM_RELAX_SEGMENTS } else { _set_limit((char *)&gdt[APM_CS >> 3], @@ -1948,6 +1971,16 @@ (apm_info.bios.cseg_16_len - 1) & 0xffff); _set_limit((char *)&gdt[APM_DS >> 3], (apm_info.bios.dseg_len - 1) & 0xffff); + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + _set_limit((char *)&gdt2[APM_CS >> 3], + (apm_info.bios.cseg_len - 1) & 0xffff); + _set_limit((char *)&gdt2[APM_CS_16 >> 3], + (apm_info.bios.cseg_16_len - 1) & 0xffff); + _set_limit((char *)&gdt2[APM_DS >> 3], + (apm_info.bios.dseg_len - 1) & 0xffff); +#endif + } #endif diff -urN linux-2.4.20/arch/i386/kernel/entry.S linux-2.4.20/arch/i386/kernel/entry.S --- linux-2.4.20/arch/i386/kernel/entry.S 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/i386/kernel/entry.S 2003-02-12 23:36:37.000000000 -0500 @@ -45,6 +45,7 @@ #include #include #include +#include EBX = 0x00 ECX = 0x04 @@ -209,6 +210,17 @@ jae badsys call *SYMBOL_NAME(sys_call_table)(,%eax,4) movl %eax,EAX(%esp) # save the return value + +#ifdef CONFIG_GRKERNSEC_PAX_RANDKSTACK + cli # need_resched and signals atomic test + cmpl $0,need_resched(%ebx) + jne reschedule + cmpl $0,sigpending(%ebx) + jne signal_return + call SYMBOL_NAME(pax_randomize_kstack) + jmp restore_all +#endif + ENTRY(ret_from_sys_call) cli # need_resched and signals atomic test cmpl $0,need_resched(%ebx) @@ -389,8 +401,56 @@ jmp error_code ENTRY(page_fault) +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + ALIGN + pushl $ SYMBOL_NAME(pax_do_page_fault) +#else pushl $ SYMBOL_NAME(do_page_fault) +#endif + +#ifndef CONFIG_GRKERNSEC_PAX_EMUTRAMP jmp error_code +#else + pushl %ds + pushl %eax + xorl %eax,%eax + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + decl %eax # eax = -1 + pushl %ecx + pushl %ebx + cld + movl %es,%ecx + movl ORIG_EAX(%esp), %esi # get the error code + movl ES(%esp), %edi # get the function address + movl %eax, ORIG_EAX(%esp) + movl %ecx, ES(%esp) + movl %esp,%edx + pushl %esi # push the error code + pushl %edx # push the pt_regs pointer + movl $(__KERNEL_DS),%edx + movl %edx,%ds + movl %edx,%es + GET_CURRENT(%ebx) + call *%edi + addl $8,%esp + decl %eax + jnz ret_from_exception + + popl %ebx + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebp + popl %eax + popl %ds + popl %es + addl $4,%esp + jmp system_call +#endif ENTRY(machine_check) pushl $0 diff -urN linux-2.4.20/arch/i386/kernel/head.S linux-2.4.20/arch/i386/kernel/head.S --- linux-2.4.20/arch/i386/kernel/head.S 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20/arch/i386/kernel/head.S 2003-02-12 23:36:37.000000000 -0500 @@ -372,6 +372,15 @@ SYMBOL_NAME(gdt): .long SYMBOL_NAME(gdt_table) +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC +.globl SYMBOL_NAME(gdt2) + .word 0 +gdt_descr2: + .word GDT_ENTRIES*8-1 +SYMBOL_NAME(gdt2): + .long SYMBOL_NAME(gdt_table2) +#endif + /* * This is initialized to create an identity-mapping at 0-8M (for bootup * purposes) and another mapping of the 0-8M area at virtual address @@ -435,6 +444,26 @@ .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */ .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ + .quad 0x0000000000000000 /* not used */ + .quad 0x0000000000000000 /* not used */ + /* + * The APM segments have byte granularity and their bases + * and limits are set at run time. + */ + .quad 0x0040920000000000 /* 0x40 APM set up for bad BIOS's */ + .quad 0x00409a0000000000 /* 0x48 APM CS code */ + .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */ + .quad 0x0040920000000000 /* 0x58 APM DS data */ + .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */ + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC +ENTRY(gdt_table2) + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x0000000000000000 /* not used */ + .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ + .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */ + .quad 0x60c5fa000000ffff /* 0x23 user 1.5GB code at 0x60000000 */ + .quad 0x00c5f2000000ffff /* 0x2b user 1.5GB data at 0x00000000 */ .quad 0x0000000000000000 /* not used */ .quad 0x0000000000000000 /* not used */ /* @@ -446,3 +475,4 @@ .quad 0x00009a0000000000 /* 0x50 APM CS 16 code (16 bit) */ .quad 0x0040920000000000 /* 0x58 APM DS data */ .fill NR_CPUS*4,8,0 /* space for TSS's and LDT's */ +#endif diff -urN linux-2.4.20/arch/i386/kernel/i386_ksyms.c linux-2.4.20/arch/i386/kernel/i386_ksyms.c --- linux-2.4.20/arch/i386/kernel/i386_ksyms.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20/arch/i386/kernel/i386_ksyms.c 2003-02-12 23:36:37.000000000 -0500 @@ -73,6 +73,9 @@ EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(apm_info); EXPORT_SYMBOL(gdt); +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC +EXPORT_SYMBOL(gdt2); +#endif EXPORT_SYMBOL(empty_zero_page); #ifdef CONFIG_DEBUG_IOVIRT diff -urN linux-2.4.20/arch/i386/kernel/ioport.c linux-2.4.20/arch/i386/kernel/ioport.c --- linux-2.4.20/arch/i386/kernel/ioport.c 1999-07-19 18:22:48.000000000 -0400 +++ linux-2.4.20/arch/i386/kernel/ioport.c 2003-02-12 23:36:37.000000000 -0500 @@ -14,6 +14,7 @@ #include #include #include +#include /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) @@ -59,8 +60,16 @@ if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32)) return -EINVAL; +#ifdef CONFIG_GRKERNSEC_IO + if (turn_on) { + gr_handle_ioperm(); +#else if (turn_on && !capable(CAP_SYS_RAWIO)) +#endif return -EPERM; +#ifdef CONFIG_GRKERNSEC_IO + } +#endif /* * If it's the first ioperm() call in this thread's lifetime, set the * IO bitmap up. ioperm() is much less timing critical than clone(), @@ -108,8 +117,13 @@ return -EINVAL; /* Trying to gain more privileges? */ if (level > old) { +#ifdef CONFIG_GRKERNSEC_IO + gr_handle_iopl(); + return -EPERM; +#else if (!capable(CAP_SYS_RAWIO)) return -EPERM; +#endif } regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12); return 0; diff -urN linux-2.4.20/arch/i386/kernel/ldt.c linux-2.4.20/arch/i386/kernel/ldt.c --- linux-2.4.20/arch/i386/kernel/ldt.c 2001-10-17 17:46:29.000000000 -0400 +++ linux-2.4.20/arch/i386/kernel/ldt.c 2003-02-12 23:36:37.000000000 -0500 @@ -122,6 +122,13 @@ } } +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + if (current->flags & PF_PAX_SEGMEXEC && (ldt_info.contents & 2)) { + error = -EINVAL; + goto out_unlock; + } +#endif + entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) | (ldt_info.limit & 0x0ffff); entry_2 = (ldt_info.base_addr & 0xff000000) | diff -urN linux-2.4.20/arch/i386/kernel/process.c linux-2.4.20/arch/i386/kernel/process.c --- linux-2.4.20/arch/i386/kernel/process.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20/arch/i386/kernel/process.c 2003-02-12 23:36:37.000000000 -0500 @@ -584,7 +584,11 @@ { struct pt_regs * childregs; +#ifdef CONFIG_GRKERNSEC_PAX_RANDKSTACK + childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p - sizeof(unsigned long))) - 1; +#else childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1; +#endif struct_cpy(childregs, regs); childregs->eax = 0; childregs->esp = esp; @@ -645,6 +649,16 @@ dump->u_fpvalid = dump_fpu (regs, &dump->i387); } +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC +void pax_reload_gdt(struct task_struct * tsk) +{ + if (tsk->flags & PF_PAX_SEGMEXEC) + __asm__ __volatile__("lgdt %0": "=m" (gdt_descr2)); + else + __asm__ __volatile__("lgdt %0": "=m" (gdt_descr)); +} +#endif + /* * This special macro can be used to load a debugging register */ @@ -684,6 +698,10 @@ unlazy_fpu(prev_p); +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + pax_reload_gdt(next_p); +#endif + /* * Reload esp0, LDT and the page table pointer: */ @@ -824,3 +842,25 @@ } #undef last_sched #undef first_sched + +#ifdef CONFIG_GRKERNSEC_PAX_RANDKSTACK +asmlinkage void pax_randomize_kstack(void) +{ + struct tss_struct *tss = init_tss + smp_processor_id(); + unsigned long time; + + rdtscl(time); + + /* P4 seems to return a 0 LSB, ignore it */ +#ifdef CONFIG_MPENTIUM4 + time &= 0x3EUL; + time <<= 1; +#else + time &= 0x1FUL; + time <<= 2; +#endif + + current->thread.esp0 ^= time; + tss->esp0 = current->thread.esp0; +} +#endif diff -urN linux-2.4.20/arch/i386/kernel/ptrace.c linux-2.4.20/arch/i386/kernel/ptrace.c --- linux-2.4.20/arch/i386/kernel/ptrace.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20/arch/i386/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,9 @@ if (pid == 1) /* you may not mess with init */ goto out_tsk; + if(gr_handle_ptrace(child, request)) + goto out_tsk; + if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out_tsk; @@ -256,6 +260,17 @@ if(addr < (long) &dummy->u_debugreg[4] && ((unsigned long) data) >= TASK_SIZE-3) break; +#ifdef CONFIG_GRKERNSEC + if(addr >= (long) &dummy->u_debugreg[0] && + addr <= (long) &dummy->u_debugreg[3]){ + long reg = (addr - (long) &dummy->u_debugreg[0]) >> 2; + long type = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 4*reg)) & 3; + long align = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 2 + 4*reg)) & 3; + if((type & 1) && (data & align)) + break; + } +#endif + if(addr == (long) &dummy->u_debugreg[7]) { data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) diff -urN linux-2.4.20/arch/i386/kernel/sys_i386.c linux-2.4.20/arch/i386/kernel/sys_i386.c --- linux-2.4.20/arch/i386/kernel/sys_i386.c 2001-03-19 15:35:09.000000000 -0500 +++ linux-2.4.20/arch/i386/kernel/sys_i386.c 2003-02-12 23:36:37.000000000 -0500 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,11 @@ int error = -EBADF; struct file * file = NULL; +#if defined(CONFIG_GRKERNSEC_PAX_SEGMEXEC) || defined(CONFIG_GRKERNSEC_PAX_RANDEXEC) + if (flags & MAP_MIRROR) + return -EINVAL; +#endif + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); @@ -55,8 +61,14 @@ goto out; } + if(gr_handle_mmap(file, prot)) { + fput(file); + error = -EACCES; + goto out; + } + down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + error = do_mmap(file, addr, len, prot, flags, pgoff << PAGE_SHIFT); up_write(¤t->mm->mmap_sem); if (file) diff -urN linux-2.4.20/arch/i386/kernel/traps.c linux-2.4.20/arch/i386/kernel/traps.c --- linux-2.4.20/arch/i386/kernel/traps.c 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/i386/kernel/traps.c 2003-02-12 23:36:37.000000000 -0500 @@ -855,11 +855,21 @@ void set_tss_desc(unsigned int n, void *addr) { _set_tssldt_desc(gdt_table+__TSS(n), (int)addr, 235, 0x89); + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + _set_tssldt_desc(gdt_table2+__TSS(n), (int)addr, 235, 0x89); +#endif + } void set_ldt_desc(unsigned int n, void *addr, unsigned int size) { _set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82); + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + _set_tssldt_desc(gdt_table2+__LDT(n), (int)addr, ((size << 3)-1), 0x82); +#endif + } #ifdef CONFIG_X86_VISWS_APIC diff -urN linux-2.4.20/arch/i386/mm/fault.c linux-2.4.20/arch/i386/mm/fault.c --- linux-2.4.20/arch/i386/mm/fault.c 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/i386/mm/fault.c 2003-02-12 23:36:37.000000000 -0500 @@ -4,6 +4,7 @@ * Copyright (C) 1995 Linus Torvalds */ +#include #include #include #include @@ -19,6 +20,8 @@ #include #include #include /* For unblank_screen() */ +#include +#include #include #include @@ -127,6 +130,11 @@ asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); extern unsigned long idt; +#if defined(CONFIG_GRKERNSEC_PAX_PAGEEXEC) || defined(CONFIG_GRKERNSEC_PAX_SEGMEXEC) +static void pax_report_fault(struct pt_regs *regs); +static int pax_handle_read_fault(struct pt_regs *regs); +#endif + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -137,23 +145,31 @@ * bit 1 == 0 means read, 1 means write * bit 2 == 0 means kernel, 1 means user-mode */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC +static int do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address) +#else +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long error_code) +#endif { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; +#ifndef CONFIG_GRKERNSEC_PAX_PAGEEXEC unsigned long address; +#endif unsigned long page; unsigned long fixup; int write; siginfo_t info; +#ifndef CONFIG_GRKERNSEC_PAX_PAGEEXEC /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); /* It's safe to allow irq's after cr2 has been saved */ - if (regs->eflags & X86_EFLAGS_IF) + if (likely(regs->eflags & X86_EFLAGS_IF)) local_irq_enable(); +#endif tsk = current; @@ -258,7 +274,7 @@ tsk->thread.screen_bitmap |= 1 << bit; } up_read(&mm->mmap_sem); - return; + return 0; /* * Something tried to access memory that isn't in our memory map.. @@ -269,6 +285,39 @@ /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + if (current->flags & PF_PAX_SEGMEXEC) { + +#if defined(CONFIG_GRKERNSEC_PAX_EMUTRAMP) || defined(CONFIG_GRKERNSEC_PAX_RANDEXEC) + if ((error_code == 4) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) { + switch (pax_handle_read_fault(regs)) { + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + case 5: + return 0; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + case 4: + return 0; + case 3: + case 2: + return 1; +#endif + + case 1: + default: + } + } +#endif + + if (address >= SEGMEXEC_TASK_SIZE) { + pax_report_fault(regs); + do_exit(SIGKILL); + } + } +#endif + tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; @@ -277,7 +326,7 @@ /* info.si_code has been set above */ info.si_addr = (void *)address; force_sig_info(SIGSEGV, &info, tsk); - return; + return 0; } /* @@ -290,7 +339,7 @@ if (nr == 6) { do_invalid_op(regs, 0); - return; + return 0; } } @@ -298,7 +347,7 @@ /* Are we prepared to handle this kernel fault? */ if ((fixup = search_exception_table(regs->eip)) != 0) { regs->eip = fixup; - return; + return 0; } /* @@ -362,7 +411,7 @@ /* Kernel mode? Handle exceptions or die */ if (!(error_code & 4)) goto no_context; - return; + return 0; vmalloc_fault: { @@ -395,6 +444,365 @@ pte_k = pte_offset(pmd_k, address); if (!pte_present(*pte_k)) goto no_context; - return; + return 0; + } +} +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC +/* PaX: called with the page_table_lock spinlock held */ +static inline pte_t * pax_get_pte(struct mm_struct *mm, unsigned long address) +{ + pgd_t *pgd; + pmd_t *pmd; + + pgd = pgd_offset(mm, address); + if (!pgd || !pgd_present(*pgd)) + return 0; + pmd = pmd_offset(pgd, address); + if (!pmd || !pmd_present(*pmd)) + return 0; + return pte_offset(pmd, address); +} +#endif + +/* + * PaX: decide what to do with offenders (regs->eip = fault address) + * + * returns 1 when task should be killed + * 2 when sigreturn trampoline was detected + * 3 when rt_sigreturn trampoline was detected + * 4 when gcc trampoline was detected + * 5 when legitimate ET_EXEC was detected + */ +#if defined(CONFIG_GRKERNSEC_PAX_PAGEEXEC) || defined(CONFIG_GRKERNSEC_PAX_SEGMEXEC) +static int pax_handle_read_fault(struct pt_regs *regs) +{ +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4}; +#endif + int err; + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + if (current->flags & PF_PAX_RANDEXEC) { + unsigned long esp_4; + if (regs->eip >= current->mm->start_code && + regs->eip < current->mm->end_code) + { + err = get_user(esp_4, (unsigned long*)(regs->esp-4UL)); + if (!err && esp_4 != regs->eip) { + regs->eip += current->mm->delta_exec; + return 5; + } + return 1; + } + } +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + +#ifndef CONFIG_GRKERNSEC_PAX_EMUSIGRT + if (!(current->flags & PF_PAX_EMUTRAMP)) + return 1; +#endif + + { /* PaX: sigreturn emulation */ + unsigned char pop, mov; + unsigned short sys; + unsigned long nr; + + err = get_user(pop, (unsigned char *)(regs->eip)); + err |= get_user(mov, (unsigned char *)(regs->eip + 1)); + err |= get_user(nr, (unsigned long *)(regs->eip + 2)); + err |= get_user(sys, (unsigned short *)(regs->eip + 6)); + + if (!err) { + if (pop == 0x58 && + mov == 0xb8 && + nr == __NR_sigreturn && + sys == 0x80cd) + { + +#ifdef CONFIG_GRKERNSEC_PAX_EMUSIGRT + int sig; + struct k_sigaction *ka; + __sighandler_t handler; + + if (get_user(sig, (int *)regs->esp)) + return 1; + if (sig < 1 || sig > _NSIG || sig == SIGKILL || sig == SIGSTOP) + return 1; + ka = ¤t->sig->action[sig-1]; + handler = ka->sa.sa_handler; + if (handler == SIG_DFL || handler == SIG_IGN) { + if (!(current->flags & PF_PAX_EMUTRAMP)) + return 1; + } else if (ka->sa.sa_flags & SA_SIGINFO) + return 1; +#endif + + regs->esp += 4; + regs->eax = nr; + regs->eip += 8; + return 2; + } + } + } + + { /* PaX: rt_sigreturn emulation */ + unsigned char mov; + unsigned short sys; + unsigned long nr; + + err = get_user(mov, (unsigned char *)(regs->eip)); + err |= get_user(nr, (unsigned long *)(regs->eip + 1)); + err |= get_user(sys, (unsigned short *)(regs->eip + 5)); + + if (!err) { + if (mov == 0xb8 && + nr == __NR_rt_sigreturn && + sys == 0x80cd) + { + +#ifdef CONFIG_GRKERNSEC_PAX_EMUSIGRT + int sig; + struct k_sigaction *ka; + __sighandler_t handler; + + if (get_user(sig, (int *)regs->esp)) + return 1; + if (sig < 1 || sig > _NSIG || sig == SIGKILL || sig == SIGSTOP) + return 1; + ka = ¤t->sig->action[sig-1]; + handler = ka->sa.sa_handler; + if (handler == SIG_DFL || handler == SIG_IGN) { + if (!(current->flags & PF_PAX_EMUTRAMP)) + return 1; + } else if (ka->sa.sa_flags & SA_SIGINFO) + return 1; +#endif + + regs->eax = nr; + regs->eip += 7; + return 3; + } + } + } + +#ifdef CONFIG_GRKERNSEC_PAX_EMUSIGRT + if (!(current->flags & PF_PAX_EMUTRAMP)) + return 1; +#endif + + { /* PaX: gcc trampoline emulation #1 */ + unsigned char mov1, mov2; + unsigned short jmp; + unsigned long addr1, addr2, ret; + + err = get_user(mov1, (unsigned char *)(regs->eip)); + err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); + err |= get_user(mov2, (unsigned char *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); + err |= get_user(jmp, (unsigned short *)(regs->eip + 10)); + err |= get_user(ret, (unsigned long *)(regs->esp)); + + if (!err) { + unsigned short call; + + err = get_user(call, (unsigned short *)(ret-2)); + if (!err) { + if ((mov1 & 0xF8) == 0xB8 && + (mov2 & 0xF8) == 0xB8 && + (mov1 & 0x07) != (mov2 & 0x07) && + (jmp & 0xF8FF) == 0xE0FF && + (mov2 & 0x07) == ((jmp>>8) & 0x07) && + (call & 0xF8FF) == 0xD0FF && + (regs->eip == ((unsigned long*)regs)[trans[(call>>8) & 0x07]])) + { + ((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1; + ((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2; + regs->eip = addr2; + return 4; + } + } + } + } + + { /* PaX: gcc trampoline emulation #2 */ + unsigned char mov, jmp; + unsigned long addr1, addr2, ret; + + err = get_user(mov, (unsigned char *)(regs->eip)); + err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); + err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); + err |= get_user(ret, (unsigned long *)(regs->esp)); + + if (!err) { + unsigned short call; + + err = get_user(call, (unsigned short *)(ret-2)); + if (!err) { + if ((mov & 0xF8) == 0xB8 && + jmp == 0xE9 && + (call & 0xF8FF) == 0xD0FF && + (regs->eip == ((unsigned long*)regs)[trans[(call>>8) & 0x07]])) + { + ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; + regs->eip += addr2 + 10; + return 4; + } + } + } } +#endif + + return 1; /* PaX in action */ } + +static void pax_report_fault(struct pt_regs *regs) +{ + struct task_struct *tsk = current; + struct mm_struct *mm = current->mm; + char* buffer = (char*)__get_free_page(GFP_ATOMIC); + char* path=NULL; + unsigned long i; + + if (buffer) { + struct vm_area_struct* vma; + + down_read(&mm->mmap_sem); + vma = mm->mmap; + while (vma) { + if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { + break; + } + vma = vma->vm_next; + } + if (vma) + path = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, buffer, PAGE_SIZE); + up_read(&mm->mmap_sem); + } + if (tsk->curr_ip) + printk(KERN_ERR "PAX: From %u.%u.%u.%u: terminating task: %.930s(%.16s):%d, uid/euid: %u/%u, " + "EIP: %08lX, ESP: %08lX\n", NIPQUAD(tsk->curr_ip), + path, tsk->comm, tsk->pid, tsk->uid, tsk->euid, + regs->eip, regs->esp); + else + printk(KERN_ERR "PAX: terminating task: %.930s(%.16s):%d, uid/euid: %u/%u, " + "EIP: %08lX, ESP: %08lX\n", path, tsk->comm, tsk->pid, + tsk->uid, tsk->euid, regs->eip, regs->esp); + + if (buffer) free_page((unsigned long)buffer); + printk(KERN_ERR "PAX: bytes at EIP: "); + for (i = 0; i < 20; i++) { + unsigned char c; + if (get_user(c, (unsigned char*)(regs->eip+i))) { + printk("."); + break; + } + printk("%02x ", c); + } + printk("\n"); + do_coredump(SIGKILL, regs); +} +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC +/* + * PaX: handle the extra page faults or pass it down to the original handler + * + * returns 0 when nothing special was detected + * 1 when sigreturn trampoline (syscall) has to be emulated + */ +asmlinkage int pax_do_page_fault(struct pt_regs *regs, unsigned long error_code) +{ + struct mm_struct *mm = current->mm; + unsigned long address; + pte_t *pte; + unsigned char pte_mask; + int ret; + + __asm__("movl %%cr2,%0":"=r" (address)); + + /* It's safe to allow irq's after cr2 has been saved */ + if (regs->eflags & X86_EFLAGS_IF) + local_irq_enable(); + + if (unlikely((error_code & 5) != 5 || + address >= TASK_SIZE || + !(current->flags & PF_PAX_PAGEEXEC))) + return do_page_fault(regs, error_code, address); + + /* PaX: it's our fault, let's handle it if we can */ + + /* PaX: take a look at read faults before acquiring any locks */ + if (unlikely((error_code == 5) && (regs->eip == address))) { + /* instruction fetch attempt from a protected page in user mode */ + ret = pax_handle_read_fault(regs); + switch (ret) { +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + case 5: + return 0; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + + case 4: + return 0; + case 3: + case 2: return 1; +#endif + case 1: + default: + pax_report_fault(regs); + do_exit(SIGKILL); + } + } + + pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1)); + + spin_lock(&mm->page_table_lock); + pte = pax_get_pte(mm, address); + if (unlikely(!pte || !(pte_val(*pte) & _PAGE_PRESENT) || pte_exec(*pte))) { + spin_unlock(&mm->page_table_lock); + do_page_fault(regs, error_code, address); + return 0; + } + + if (unlikely((error_code == 7) && !pte_write(*pte))) { + /* write attempt to a protected page in user mode */ + spin_unlock(&mm->page_table_lock); + do_page_fault(regs, error_code, address); + return 0; + } + + /* + * PaX: fill DTLB with user rights and retry + */ + __asm__ __volatile__ ( + "orb %2,%1\n" +#if defined(CONFIG_M586) || defined(CONFIG_M586TSC) +/* + * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's + * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any* + * page fault when examined during a TLB load attempt. this is true not only + * for PTEs holding a non-present entry but also present entries that will + * raise a page fault (such as those set up by PaX, or the copy-on-write + * mechanism). in effect it means that we do *not* need to flush the TLBs + * for our target pages since their PTEs are simply not in the TLBs at all. + * the best thing in omitting it is that we gain around 15-20% speed in + * fast path of the page fault handler and can get rid of tracing since we + * can no longer flush unintended entries. + */ + + "invlpg %0\n" +#endif + + "testb $0,%0\n" + "xorb %3,%1\n" + : + : "m" (*(char*)address), "m" (*(char*)pte) , "q" (pte_mask) , "i" (_PAGE_USER) + : "memory", "cc"); + spin_unlock(&mm->page_table_lock); + return 0; +} +#endif diff -urN linux-2.4.20/arch/ia64/config.in linux-2.4.20/arch/ia64/config.in --- linux-2.4.20/arch/ia64/config.in 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/ia64/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -293,3 +293,12 @@ fi endmenu + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -urN linux-2.4.20/arch/ia64/kernel/ptrace.c linux-2.4.20/arch/ia64/kernel/ptrace.c --- linux-2.4.20/arch/ia64/kernel/ptrace.c 2002-08-02 20:39:42.000000000 -0400 +++ linux-2.4.20/arch/ia64/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1118,6 +1119,9 @@ if (pid == 1) /* no messing around with init! */ goto out_tsk; + if (gr_handle_ptrace(child, request)) + goto out_tsk; + if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out_tsk; diff -urN linux-2.4.20/arch/ia64/kernel/sys_ia64.c linux-2.4.20/arch/ia64/kernel/sys_ia64.c --- linux-2.4.20/arch/ia64/kernel/sys_ia64.c 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/ia64/kernel/sys_ia64.c 2003-02-12 23:36:37.000000000 -0500 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -212,6 +213,11 @@ goto out; } + if (gr_handle_mmap(file, prot)) { + addr = -EACCES; + goto out; + } + down_write(¤t->mm->mmap_sem); addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); diff -urN linux-2.4.20/arch/m68k/config.in linux-2.4.20/arch/m68k/config.in --- linux-2.4.20/arch/m68k/config.in 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/m68k/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -558,3 +558,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/mips/config.in linux-2.4.20/arch/mips/config.in --- linux-2.4.20/arch/mips/config.in 2002-11-28 18:53:09.000000000 -0500 +++ linux-2.4.20/arch/mips/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -7,3 +7,11 @@ define_bool CONFIG_MIPS64 n source arch/mips/config-shared.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/mips64/config.in linux-2.4.20/arch/mips64/config.in --- linux-2.4.20/arch/mips64/config.in 2002-11-28 18:53:10.000000000 -0500 +++ linux-2.4.20/arch/mips64/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -7,3 +7,11 @@ define_bool CONFIG_MIPS64 y source arch/mips/config-shared.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/parisc/config.in linux-2.4.20/arch/parisc/config.in --- linux-2.4.20/arch/parisc/config.in 2002-11-28 18:53:10.000000000 -0500 +++ linux-2.4.20/arch/parisc/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -197,3 +197,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/parisc/kernel/ioctl32.c linux-2.4.20/arch/parisc/kernel/ioctl32.c --- linux-2.4.20/arch/parisc/kernel/ioctl32.c 2002-11-28 18:53:10.000000000 -0500 +++ linux-2.4.20/arch/parisc/kernel/ioctl32.c 2003-02-12 23:36:37.000000000 -0500 @@ -1434,7 +1434,11 @@ * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or super-user. */ +#ifdef CONFIG_GRKERNSEC + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) +#else if (current->tty == tty || suser()) +#endif return 1; return 0; } diff -urN linux-2.4.20/arch/parisc/kernel/ptrace.c linux-2.4.20/arch/parisc/kernel/ptrace.c --- linux-2.4.20/arch/parisc/kernel/ptrace.c 2002-11-28 18:53:10.000000000 -0500 +++ linux-2.4.20/arch/parisc/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -15,7 +15,7 @@ #include #include #include - +#include #include #include #include @@ -119,6 +119,9 @@ if (pid == 1) /* no messing around with init! */ goto out_tsk; + if (gr_handle_ptrace(child, ptrace)) + goto out_tsk; + if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out_tsk; diff -urN linux-2.4.20/arch/parisc/kernel/sys_parisc.c linux-2.4.20/arch/parisc/kernel/sys_parisc.c --- linux-2.4.20/arch/parisc/kernel/sys_parisc.c 2002-11-28 18:53:10.000000000 -0500 +++ linux-2.4.20/arch/parisc/kernel/sys_parisc.c 2003-02-12 23:36:37.000000000 -0500 @@ -12,6 +12,7 @@ #include #include #include +#include int sys_pipe(int *fildes) { @@ -110,6 +111,11 @@ goto out; } + if (gr_handle_mmap(file, prot)) { + fput(file); + return -EACCES; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); diff -urN linux-2.4.20/arch/ppc/config.in linux-2.4.20/arch/ppc/config.in --- linux-2.4.20/arch/ppc/config.in 2002-11-28 18:53:11.000000000 -0500 +++ linux-2.4.20/arch/ppc/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -425,3 +425,12 @@ fi fi endmenu + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu + diff -urN linux-2.4.20/arch/ppc/kernel/ptrace.c linux-2.4.20/arch/ppc/kernel/ptrace.c --- linux-2.4.20/arch/ppc/kernel/ptrace.c 2002-11-28 18:53:11.000000000 -0500 +++ linux-2.4.20/arch/ppc/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -185,6 +186,9 @@ if (pid == 1) /* you may not mess with init */ goto out_tsk; + if (gr_handle_ptrace(child, request)) + goto out_tsk; + if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out_tsk; diff -urN linux-2.4.20/arch/ppc/kernel/syscalls.c linux-2.4.20/arch/ppc/kernel/syscalls.c --- linux-2.4.20/arch/ppc/kernel/syscalls.c 2002-08-02 20:39:43.000000000 -0400 +++ linux-2.4.20/arch/ppc/kernel/syscalls.c 2003-02-12 23:36:37.000000000 -0500 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -202,6 +203,12 @@ goto out; } + if (gr_handle_mmap(file, prot)) { + fput(file); + ret = -EACCES; + goto out; + } + down_write(¤t->mm->mmap_sem); ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); diff -urN linux-2.4.20/arch/ppc64/kernel/ioctl32.c linux-2.4.20/arch/ppc64/kernel/ioctl32.c --- linux-2.4.20/arch/ppc64/kernel/ioctl32.c 2002-11-28 18:53:11.000000000 -0500 +++ linux-2.4.20/arch/ppc64/kernel/ioctl32.c 2003-02-12 23:36:37.000000000 -0500 @@ -1761,7 +1761,11 @@ * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or super-user. */ +#ifdef CONFIG_GRKERNSEC + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) +#else if (current->tty == tty || suser()) +#endif return 1; return 0; } diff -urN linux-2.4.20/arch/s390/config.in linux-2.4.20/arch/s390/config.in --- linux-2.4.20/arch/s390/config.in 2002-11-28 18:53:11.000000000 -0500 +++ linux-2.4.20/arch/s390/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -76,3 +76,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/s390x/config.in linux-2.4.20/arch/s390x/config.in --- linux-2.4.20/arch/s390x/config.in 2002-11-28 18:53:11.000000000 -0500 +++ linux-2.4.20/arch/s390x/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -80,3 +80,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/sh/config.in linux-2.4.20/arch/sh/config.in --- linux-2.4.20/arch/sh/config.in 2002-11-28 18:53:11.000000000 -0500 +++ linux-2.4.20/arch/sh/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -388,3 +388,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/sparc/config.in linux-2.4.20/arch/sparc/config.in --- linux-2.4.20/arch/sparc/config.in 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/arch/sparc/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -268,3 +268,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/sparc/kernel/ptrace.c linux-2.4.20/arch/sparc/kernel/ptrace.c --- linux-2.4.20/arch/sparc/kernel/ptrace.c 2002-08-02 20:39:43.000000000 -0400 +++ linux-2.4.20/arch/sparc/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -310,6 +311,9 @@ goto out; } + if(gr_handle_ptrace(child, request)) + goto out_tsk; + if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { if (ptrace_attach(child)) { diff -urN linux-2.4.20/arch/sparc/kernel/sys_sparc.c linux-2.4.20/arch/sparc/kernel/sys_sparc.c --- linux-2.4.20/arch/sparc/kernel/sys_sparc.c 2001-04-13 23:15:55.000000000 -0400 +++ linux-2.4.20/arch/sparc/kernel/sys_sparc.c 2003-02-12 23:36:37.000000000 -0500 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -240,6 +241,12 @@ if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) goto out_putf; + if (gr_handle_mmap(file, prot)) { + fput(file); + retval = -EACCES; + goto out; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); diff -urN linux-2.4.20/arch/sparc64/config.in linux-2.4.20/arch/sparc64/config.in --- linux-2.4.20/arch/sparc64/config.in 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/arch/sparc64/config.in 2003-02-12 23:36:37.000000000 -0500 @@ -310,3 +310,11 @@ endmenu source lib/Config.in + +mainmenu_option next_comment +comment 'Grsecurity' +bool 'Grsecurity' CONFIG_GRKERNSEC +if [ "$CONFIG_GRKERNSEC" = "y" ]; then + source grsecurity/Config.in +fi +endmenu diff -urN linux-2.4.20/arch/sparc64/kernel/ioctl32.c linux-2.4.20/arch/sparc64/kernel/ioctl32.c --- linux-2.4.20/arch/sparc64/kernel/ioctl32.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/arch/sparc64/kernel/ioctl32.c 2003-02-12 23:36:37.000000000 -0500 @@ -2133,7 +2133,11 @@ * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or super-user. */ +#ifdef CONFIG_GRKERNSEC + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) +#else if (current->tty == tty || suser()) +#endif return 1; return 0; } diff -urN linux-2.4.20/arch/sparc64/kernel/ptrace.c linux-2.4.20/arch/sparc64/kernel/ptrace.c --- linux-2.4.20/arch/sparc64/kernel/ptrace.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/arch/sparc64/kernel/ptrace.c 2003-02-12 23:36:37.000000000 -0500 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,11 @@ goto out; } + if (gr_handle_ptrace(child, (long)request)) { + pt_error_return(regs, EPERM); + goto out; + } + if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { if (ptrace_attach(child)) { diff -urN linux-2.4.20/arch/sparc64/kernel/sys_sparc.c linux-2.4.20/arch/sparc64/kernel/sys_sparc.c --- linux-2.4.20/arch/sparc64/kernel/sys_sparc.c 2002-08-02 20:39:43.000000000 -0400 +++ linux-2.4.20/arch/sparc64/kernel/sys_sparc.c 2003-02-12 23:36:37.000000000 -0500 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -76,6 +77,11 @@ addr = PAGE_ALIGN(addr); task_size -= len; +#ifdef CONFIG_GRKERNSEC_PAX_RANDMMAP + if (current->flags & PF_PAX_RANDMMAP) + addr += current->mm->delta_mmap; +#endif + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { /* At this point: (!vmm || addr < vmm->vm_end). */ if (addr < PAGE_OFFSET && -PAGE_OFFSET - len < addr) { @@ -285,6 +291,12 @@ if (!file) goto out; } + + if (gr_handle_mmap(file, prot)) { + retval = -EACCES; + goto out_putf; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); len = PAGE_ALIGN(len); retval = -EINVAL; diff -urN linux-2.4.20/arch/sparc64/kernel/sys_sparc32.c linux-2.4.20/arch/sparc64/kernel/sys_sparc32.c --- linux-2.4.20/arch/sparc64/kernel/sys_sparc32.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/arch/sparc64/kernel/sys_sparc32.c 2003-02-12 23:36:37.000000000 -0500 @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -3111,6 +3113,15 @@ int i; bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + +#ifdef CONFIG_GRKERNSEC_PAX_RANDUSTACK + { + unsigned short delta; + get_random_bytes(&delta, sizeof(delta)); + bprm.p -= (delta & ~(sizeof(void *)-1)) & ~PAGE_MASK; + } +#endif + memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); file = open_exec(filename); @@ -3119,6 +3130,20 @@ if (IS_ERR(file)) return retval; + gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes)); + + if (gr_handle_nproc()) { + allow_write_access(file); + fput(file); + return -EAGAIN; + } + + if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) { + allow_write_access(file); + fput(file); + return -EACCES; + } + bprm.file = file; bprm.filename = filename; bprm.sh_bang = 0; @@ -3139,11 +3164,26 @@ if (retval < 0) goto out; + if(!gr_tpe_allow(file)) { + retval = -EACCES; + goto out; + } + + if (gr_check_crash_exec(file)) { + retval = -EACCES; + goto out; + } + retval = copy_strings_kernel(1, &bprm.filename, &bprm); if (retval < 0) goto out; bprm.exec = bprm.p; + + gr_set_proc_label(file->f_dentry, file->f_vfsmnt); + + gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); + retval = copy_strings32(bprm.envc, envp, &bprm); if (retval < 0) goto out; diff -urN linux-2.4.20/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.20/arch/x86_64/ia32/ia32_ioctl.c --- linux-2.4.20/arch/x86_64/ia32/ia32_ioctl.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/arch/x86_64/ia32/ia32_ioctl.c 2003-02-12 23:36:37.000000000 -0500 @@ -1660,7 +1660,11 @@ * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or super-user. */ +#ifdef CONFIG_GRKERNSEC + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) +#else if (current->tty == tty || suser()) +#endif return 1; return 0; } diff -urN linux-2.4.20/drivers/char/mem.c linux-2.4.20/drivers/char/mem.c --- linux-2.4.20/drivers/char/mem.c 2002-08-02 20:39:43.000000000 -0400 +++ linux-2.4.20/drivers/char/mem.c 2003-02-12 23:36:37.000000000 -0500 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -114,6 +115,11 @@ unsigned long p = *ppos; unsigned long end_mem; +#ifdef CONFIG_GRKERNSEC_KMEM + gr_handle_mem_write(); + return -EPERM; +#endif + end_mem = __pa(high_memory); if (p >= end_mem) return 0; @@ -186,6 +192,12 @@ { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; +#ifdef CONFIG_GRKERNSEC_KMEM + if (gr_handle_mem_mmap(offset, vma)) + return -EPERM; +#endif + + /* * Accessing memory above the top the kernel knows about or * through a file pointer that was marked O_SYNC will be @@ -285,6 +297,11 @@ ssize_t virtr = 0; char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ +#ifdef CONFIG_GRKERNSEC_KMEM + gr_handle_kmem_write(); + return -EPERM; +#endif + if (p < (unsigned long) high_memory) { wrote = count; if (count > (unsigned long) high_memory - p) @@ -401,7 +418,7 @@ count = size; zap_page_range(mm, addr, count); - zeromap_page_range(addr, count, PAGE_COPY); + zeromap_page_range(addr, count, vma->vm_page_prot); size -= count; buf += count; @@ -517,6 +534,15 @@ static int open_port(struct inode * inode, struct file * filp) { +#ifdef CONFIG_GRKERNSEC_KMEM + gr_handle_open_port(); + return -EPERM; +#endif + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static int open_mem(struct inode * inode, struct file * filp) +{ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } @@ -525,7 +551,6 @@ #define full_lseek null_lseek #define write_zero write_null #define read_full read_zero -#define open_mem open_port #define open_kmem open_mem static struct file_operations mem_fops = { diff -urN linux-2.4.20/drivers/char/random.c linux-2.4.20/drivers/char/random.c --- linux-2.4.20/drivers/char/random.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/drivers/char/random.c 2003-02-12 23:36:37.000000000 -0500 @@ -260,9 +260,15 @@ /* * Configuration information */ +#ifdef CONFIG_GRKERNSEC_RANDNET +#define DEFAULT_POOL_SIZE 1024 +#define SECONDARY_POOL_SIZE 256 +#define BATCH_ENTROPY_SIZE 512 +#else #define DEFAULT_POOL_SIZE 512 #define SECONDARY_POOL_SIZE 128 #define BATCH_ENTROPY_SIZE 256 +#endif #define USE_SHA /* @@ -387,6 +393,7 @@ /* * Static global variables */ + static struct entropy_store *random_state; /* The default global store */ static struct entropy_store *sec_random_state; /* secondary store */ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); diff -urN linux-2.4.20/drivers/char/tty_io.c linux-2.4.20/drivers/char/tty_io.c --- linux-2.4.20/drivers/char/tty_io.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/drivers/char/tty_io.c 2003-02-12 23:36:37.000000000 -0500 @@ -99,7 +99,7 @@ #include #include #include - +#include #include #ifdef CONFIG_VT @@ -1380,7 +1380,11 @@ retval = -ENODEV; filp->f_flags = saved_flags; +#ifdef CONFIG_GRKERNSEC + if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_TTY_CONFIG)) +#else if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser()) +#endif retval = -EBUSY; if (retval) { @@ -1482,7 +1486,11 @@ { char ch, mbz = 0; +#ifdef CONFIG_GRKERNSEC + if ((current->tty != tty) && !capable(CAP_SYS_TTY_CONFIG)) +#else if ((current->tty != tty) && !suser()) +#endif return -EPERM; if (get_user(ch, arg)) return -EFAULT; @@ -1520,7 +1528,11 @@ { if (inode->i_rdev == SYSCONS_DEV || inode->i_rdev == CONSOLE_DEV) { +#ifdef CONFIG_GRKERNSEC + if (!capable(CAP_SYS_TTY_CONFIG)) +#else if (!suser()) +#endif return -EPERM; redirect = NULL; return 0; @@ -1562,7 +1574,11 @@ * This tty is already the controlling * tty for another session group! */ +#ifdef CONFIG_GRKERNSEC + if ((arg == 1) && capable(CAP_SYS_ADMIN)) { +#else if ((arg == 1) && suser()) { +#endif /* * Steal it away */ diff -urN linux-2.4.20/drivers/char/vt.c linux-2.4.20/drivers/char/vt.c --- linux-2.4.20/drivers/char/vt.c 2002-11-28 18:53:12.000000000 -0500 +++ linux-2.4.20/drivers/char/vt.c 2003-02-12 23:36:37.000000000 -0500 @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef CONFIG_FB_COMPAT_XPMAC #include @@ -443,7 +444,11 @@ * to be the owner of the tty, or super-user. */ perm = 0; +#ifdef CONFIG_GRKERNSEC + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) +#else if (current->tty == tty || suser()) +#endif perm = 1; kbd = kbd_table + console; @@ -1038,12 +1043,20 @@ return do_unimap_ioctl(cmd, (struct unimapdesc *)arg, perm); case VT_LOCKSWITCH: +#ifdef CONFIG_GRKERNSEC + if (!capable(CAP_SYS_TTY_CONFIG)) +#else if (!suser()) +#endif return -EPERM; vt_dont_switch = 1; return 0; case VT_UNLOCKSWITCH: +#ifdef CONFIG_GRKERNSEC + if (!capable(CAP_SYS_TTY_CONFIG)) +#else if (!suser()) +#endif return -EPERM; vt_dont_switch = 0; return 0; diff -urN linux-2.4.20/drivers/pci/proc.c linux-2.4.20/drivers/pci/proc.c --- linux-2.4.20/drivers/pci/proc.c 2002-11-28 18:53:14.000000000 -0500 +++ linux-2.4.20/drivers/pci/proc.c 2003-02-12 23:36:37.000000000 -0500 @@ -562,7 +562,15 @@ pci_for_each_dev(dev) { pci_proc_attach_device(dev); } +#ifdef CONFIG_GRKERNSEC_PROC_ADD +#ifdef CONFIG_GRKERNSEC_PROC_USER + entry = create_proc_entry("pci", S_IRUSR, NULL); +#elif CONFIG_GRKERNSEC_PROC_USERGROUP + entry = create_proc_entry("pci", S_IRUSR | S_IRGRP, NULL); +#endif +#else entry = create_proc_entry("pci", 0, NULL); +#endif if (entry) entry->proc_fops = &proc_pci_operations; } diff -urN linux-2.4.20/fs/binfmt_aout.c linux-2.4.20/fs/binfmt_aout.c --- linux-2.4.20/fs/binfmt_aout.c 2001-11-02 20:39:20.000000000 -0500 +++ linux-2.4.20/fs/binfmt_aout.c 2003-02-12 23:36:37.000000000 -0500 @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -113,10 +114,12 @@ /* If the size of the dump file exceeds the rlimit, then see what would happen if we wrote the stack, but not the data area. */ #ifdef __sparc__ + gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize+dump.u_ssize); if ((dump.u_dsize+dump.u_ssize) > current->rlim[RLIMIT_CORE].rlim_cur) dump.u_dsize = 0; #else + gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE); if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE > current->rlim[RLIMIT_CORE].rlim_cur) dump.u_dsize = 0; @@ -124,10 +127,12 @@ /* Make sure we have enough room to write the stack and data areas. */ #ifdef __sparc__ + gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize); if ((dump.u_ssize) > current->rlim[RLIMIT_CORE].rlim_cur) dump.u_ssize = 0; #else + gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize+1) * PAGE_SIZE); if ((dump.u_ssize+1) * PAGE_SIZE > current->rlim[RLIMIT_CORE].rlim_cur) dump.u_ssize = 0; @@ -276,6 +281,8 @@ rlim = current->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; + + gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss); if (ex.a_data + ex.a_bss > rlim) return -ENOMEM; @@ -307,6 +314,24 @@ current->mm->mmap = NULL; compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; + +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) { + current->flags |= PF_PAX_PAGEEXEC; + +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + if (N_FLAGS(ex) & F_PAX_EMUTRAMP) + current->flags |= PF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_MPROTECT + if (!(N_FLAGS(ex) & F_PAX_MPROTECT)) + current->flags |= PF_PAX_MPROTECT; +#endif + + } +#endif + #ifdef __sparc__ if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; @@ -393,7 +418,7 @@ down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, - PROT_READ | PROT_WRITE | PROT_EXEC, + PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); up_write(¤t->mm->mmap_sem); diff -urN linux-2.4.20/fs/binfmt_elf.c linux-2.4.20/fs/binfmt_elf.c --- linux-2.4.20/fs/binfmt_elf.c 2002-08-02 20:39:45.000000000 -0400 +++ linux-2.4.20/fs/binfmt_elf.c 2003-02-12 23:36:37.000000000 -0500 @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -33,10 +34,13 @@ #include #include #include +#include +#include #include #include #include +#include #define DLINFO_ITEMS 13 @@ -86,6 +90,12 @@ if (end <= start) return; do_brk(start, end - start); + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + if (current->flags & PF_PAX_RANDEXEC) + do_mmap_pgoff(NULL, start + current->mm->delta_exec, 0UL, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, start); +#endif + } @@ -444,6 +454,11 @@ struct elfhdr interp_elf_ex; struct exec interp_ex; char passed_fileno[6]; + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + unsigned long load_addr_random = 0UL; + unsigned long load_bias_random = 0UL; +#endif /* Get the exec-header */ elf_ex = *((struct elfhdr *) bprm->buf); @@ -598,7 +613,79 @@ current->mm->end_data = 0; current->mm->end_code = 0; current->mm->mmap = NULL; + +#ifdef CONFIG_GRKERNSEC_PAX_ASLR + current->mm->delta_mmap = 0UL; + current->mm->delta_exec = 0UL; + current->mm->delta_stack = 0UL; +#endif + current->flags &= ~PF_FORKNOEXEC; + +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + if (!(elf_ex.e_ident[EI_PAX] & EF_PAX_PAGEEXEC)) + current->flags |= PF_PAX_PAGEEXEC; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + if (elf_ex.e_ident[EI_PAX] & EF_PAX_EMUTRAMP) + current->flags |= PF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_MPROTECT + if (!(elf_ex.e_ident[EI_PAX] & EF_PAX_MPROTECT)) + current->flags |= PF_PAX_MPROTECT; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_ASLR + if (!(elf_ex.e_ident[EI_PAX] & EF_PAX_RANDMMAP)) { + unsigned long delta; + current->flags |= PF_PAX_RANDMMAP; + +#ifdef CONFIG_SPARC64 +#define pax_delta_mask(delta, shift) \ + (current->thread.flags & SPARC_FLAG_32BIT) ? \ + ((delta & (((__u32)1 << (8*sizeof(__u32) - 4 - (shift + 1))) - 1)) << (shift + 1)) \ + : ((delta & ((1UL << (8*sizeof(unsigned long) - 22 - (shift + 1))) - 1)) << (shift + 1)) +#else +#define pax_delta_mask(delta, shift) \ + ((delta & ((1UL << (8*sizeof(unsigned long) - 4 - shift)) - 1)) << shift) +#endif + + delta = (unsigned long) arc4random(); + current->mm->delta_mmap = pax_delta_mask(delta, PAGE_SHIFT); + + delta = (unsigned long) arc4random(); + current->mm->delta_exec = pax_delta_mask(delta, PAGE_SHIFT); + + delta = (unsigned long) arc4random(); + current->mm->delta_stack = pax_delta_mask(delta, PAGE_SHIFT); +#undef pax_delta_mask + } +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + if (!(elf_ex.e_ident[EI_PAX] & EF_PAX_SEGMEXEC)) { + current->flags &= ~PF_PAX_PAGEEXEC; + current->flags |= PF_PAX_SEGMEXEC; + +#ifdef CONFIG_GRKERNSEC_PAX_ASLR + current->mm->delta_mmap &= 0x07FFFFFFUL; + current->mm->delta_exec &= 0x07FFFFFFUL; + current->mm->delta_stack &= 0x07FFFFFFUL; +#endif + + } +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + if ((elf_ex.e_ident[EI_PAX] & EF_PAX_RANDEXEC) && (elf_ex.e_type == ET_EXEC) && + (current->flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC))) + current->flags |= PF_PAX_RANDEXEC; +#endif + + gr_set_pax_flags(current); + elf_entry = (unsigned long) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will @@ -654,11 +741,84 @@ base, as well as whatever program they might try to exec. This is because the brk will follow the loader, and is not movable. */ load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); + +#ifdef CONFIG_GRKERNSEC_PAX_RANDMMAP + /* PaX: randomize base address at the default exe base if requested */ + if (current->flags & PF_PAX_RANDMMAP) { + load_bias = ELF_PAGESTART(0x08048000 - vaddr + current->mm->delta_exec); + elf_flags |= MAP_FIXED; + } +#endif + } - error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); - if (BAD_ADDR(error)) - continue; +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + if ((current->flags & PF_PAX_RANDEXEC) && (elf_ex.e_type == ET_EXEC)) { + unsigned long addr, len; + + error = -ENOMEM; + +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + if (current->flags & PF_PAX_PAGEEXEC) + error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot & ~PROT_EXEC, elf_flags); +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + if (current->flags & PF_PAX_SEGMEXEC) { + addr = ELF_PAGESTART(load_bias + vaddr); + len = elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr); + if (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len) + continue; + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(bprm->file, addr, len, elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)) >> PAGE_SHIFT); + up_write(¤t->mm->mmap_sem); + } +#endif + + if (BAD_ADDR(error)) + continue; + + /* PaX: mirror at a randomized base */ + down_write(¤t->mm->mmap_sem); + + if (!load_addr_set) { + load_addr_random = get_unmapped_area(bprm->file, 0UL, elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr), (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)) >> PAGE_SHIFT, MAP_PRIVATE); + if (BAD_ADDR(load_addr_random)) { + up_write(¤t->mm->mmap_sem); + continue; + } + load_bias_random = load_addr_random - vaddr; + } + +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + if (current->flags & PF_PAX_PAGEEXEC) + load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), 0UL, elf_prot, elf_flags | MAP_MIRROR, error); +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + if (current->flags & PF_PAX_SEGMEXEC) { + if (elf_prot & PROT_EXEC) { + load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), elf_ppnt->p_memsz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr), PROT_NONE, MAP_PRIVATE | MAP_FIXED, 0UL); + if (!BAD_ADDR(load_addr_random)) { + load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr + SEGMEXEC_TASK_SIZE), 0UL, elf_prot, elf_flags | MAP_MIRROR, error); + if (!BAD_ADDR(load_addr_random)) + load_addr_random -= SEGMEXEC_TASK_SIZE; + } + } else + load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), 0UL, elf_prot, elf_flags | MAP_MIRROR, error); + } +#endif + + up_write(¤t->mm->mmap_sem); + if (BAD_ADDR(load_addr_random)) + continue; + } else +#endif + { + error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); + if (BAD_ADDR(error)) + continue; + } if (!load_addr_set) { load_addr_set = 1; @@ -668,6 +828,11 @@ ELF_PAGESTART(load_bias + vaddr); load_addr += load_bias; } + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + current->mm->delta_exec = load_addr_random - load_addr; +#endif + } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; @@ -694,6 +859,13 @@ start_data += load_bias; end_data += load_bias; + /* Calling set_brk effectively mmaps the pages that we need + * for the bss and break sections + */ + set_brk(elf_bss, elf_brk); + + padzero(elf_bss); + if (elf_interpreter) { if (interpreter_type == INTERPRETER_AOUT) elf_entry = load_aout_interp(&interp_ex, @@ -742,13 +914,6 @@ current->mm->end_data = end_data; current->mm->start_stack = bprm->p; - /* Calling set_brk effectively mmaps the pages that we need - * for the bss and break sections - */ - set_brk(elf_bss, elf_brk); - - padzero(elf_bss); - #if 0 printk("(start_brk) %lx\n" , (long) current->mm->start_brk); printk("(end_code) %lx\n" , (long) current->mm->end_code); @@ -781,6 +946,10 @@ ELF_PLAT_INIT(regs); #endif +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + pax_reload_gdt(current); +#endif + start_thread(regs, elf_entry, bprm->p); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); @@ -1003,8 +1172,11 @@ #undef DUMP_SEEK #define DUMP_WRITE(addr, nr) \ + do { \ + gr_learn_resource(current, RLIMIT_CORE, size + (nr)); \ if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ - goto end_coredump; + goto end_coredump; \ + } while (0); #define DUMP_SEEK(off) \ if (!dump_seek(file, (off))) \ goto end_coredump; diff -urN linux-2.4.20/fs/buffer.c linux-2.4.20/fs/buffer.c --- linux-2.4.20/fs/buffer.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/buffer.c 2003-02-12 23:36:37.000000000 -0500 @@ -1786,6 +1786,9 @@ int err; err = -EFBIG; + + gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long) size); + limit = current->rlim[RLIMIT_FSIZE].rlim_cur; if (limit != RLIM_INFINITY && size > (loff_t)limit) { send_sig(SIGXFSZ, current, 0); diff -urN linux-2.4.20/fs/exec.c linux-2.4.20/fs/exec.c --- linux-2.4.20/fs/exec.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/exec.c 2003-02-12 23:36:37.000000000 -0500 @@ -41,6 +41,9 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_KMOD #include @@ -299,6 +302,11 @@ lru_cache_add(page); flush_dcache_page(page); flush_page_to_ram(page); +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + if (tsk->flags & PF_PAX_PAGEEXEC) + set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY_NOEXEC)))); + else +#endif set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY)))); tsk->mm->rss++; spin_unlock(&tsk->mm->page_table_lock); @@ -334,8 +342,14 @@ mpnt->vm_mm = current->mm; mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = STACK_TOP; - mpnt->vm_page_prot = PAGE_COPY; mpnt->vm_flags = VM_STACK_FLAGS; + +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + if (!(current->flags & PF_PAX_PAGEEXEC)) + mpnt->vm_page_prot = protection_map[(mpnt->vm_flags | VM_EXEC) & 0x0f]; + else +#endif + mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x0f]; mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; @@ -584,6 +598,30 @@ } current->comm[i] = '\0'; +#ifdef CONFIG_GRKERNSEC_PAX_PAGEEXEC + current->flags &= ~PF_PAX_PAGEEXEC; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_EMUTRAMP + current->flags &= ~PF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_MPROTECT + current->flags &= ~PF_PAX_MPROTECT; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_ASLR + current->flags &= ~PF_PAX_RANDMMAP; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_RANDEXEC + current->flags &= ~PF_PAX_RANDEXEC; +#endif + +#ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC + current->flags &= ~PF_PAX_SEGMEXEC; +#endif + flush_thread(); de_thread(current); @@ -681,6 +719,9 @@ cap_set_full(bprm->cap_effective); } + if (gr_handle_ptrace_exec(bprm->file->f_dentry, bprm->file->f_vfsmnt)) + return -EACCES; + memset(bprm->buf,0,BINPRM_BUF_SIZE); return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); } @@ -886,7 +927,30 @@ if (IS_ERR(file)) return retval; + gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes)); + + if (gr_handle_nproc()) { + allow_write_access(file); + fput(file); + return -EAGAIN; + } + + if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) { + allow_write_access(file); + fput(file); + return -EACCES; + } + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + +#ifdef CONFIG_GRKERNSEC_PAX_RANDUSTACK + { + unsigned short delta; + get_random_bytes(&delta, sizeof(delta)); + bprm.p -= (delta & ~(sizeof(void *)-1)) & ~PAGE_MASK; + } +#endif + memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); bprm.file = file; @@ -910,11 +974,28 @@ if (retval < 0) goto out; + if (!gr_tpe_allow(file)) { + retval = -EACCES; + goto out; + } + + if(gr_check_crash_exec(file)) { + retval = -EACCES; + goto out; + } + retval = copy_strings_kernel(1, &bprm.filename, &bprm); if (retval < 0) goto out; bprm.exec = bprm.p; + + gr_set_proc_label(file->f_dentry, file->f_vfsmnt); + + gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); + + gr_handle_exec_args(&bprm, argv); + retval = copy_strings(bprm.envc, envp, &bprm); if (retval < 0) goto out; @@ -968,6 +1049,7 @@ if (!current->mm->dumpable) goto fail; current->mm->dumpable = 0; + gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump); if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) goto fail; @@ -989,7 +1071,7 @@ goto close_fail; if (!file->f_op->write) goto close_fail; - if (do_truncate(file->f_dentry, 0) != 0) + if (do_truncate(file->f_dentry, 0, file->f_vfsmnt) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file); diff -urN linux-2.4.20/fs/fcntl.c linux-2.4.20/fs/fcntl.c --- linux-2.4.20/fs/fcntl.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/fcntl.c 2003-02-12 23:36:37.000000000 -0500 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,7 @@ write_lock(&files->file_lock); error = -EINVAL; + gr_learn_resource(current, RLIMIT_NOFILE, orig_start); if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur) goto out; @@ -86,6 +88,7 @@ } error = -EMFILE; + gr_learn_resource(current, RLIMIT_NOFILE, newfd); if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) goto out; @@ -148,6 +151,7 @@ if (newfd == oldfd) goto out_unlock; err = -EBADF; + gr_learn_resource(current, RLIMIT_NOFILE, newfd); if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) goto out_unlock; get_file(file); /* We are now finished with oldfd */ @@ -448,6 +452,8 @@ match = -p->pgrp; if (pid != match) continue; + if (gr_pid_is_chrooted(p)) + continue; send_sigio_to_task(p, fown, fd, band); } out: diff -urN linux-2.4.20/fs/locks.c linux-2.4.20/fs/locks.c --- linux-2.4.20/fs/locks.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/locks.c 2003-02-12 23:36:37.000000000 -0500 @@ -138,6 +138,7 @@ static struct file_lock *locks_alloc_lock(int account) { struct file_lock *fl; + if(account) gr_learn_resource(current, RLIMIT_LOCKS, current->locks); if (account && current->locks >= current->rlim[RLIMIT_LOCKS].rlim_cur) return NULL; fl = kmem_cache_alloc(filelock_cache, SLAB_KERNEL); diff -urN linux-2.4.20/fs/namei.c linux-2.4.20/fs/namei.c --- linux-2.4.20/fs/namei.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/namei.c 2003-02-12 23:36:37.000000000 -0500 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -343,6 +344,13 @@ current->state = TASK_RUNNING; schedule(); } + + if (gr_handle_follow_link(dentry->d_parent->d_inode, + dentry->d_inode, dentry, nd->mnt)) { + path_release(nd); + return -EACCES; + } + current->link_count++; current->total_link_count++; UPDATE_ATIME(dentry->d_inode); @@ -641,6 +649,10 @@ } } return_base: + if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt)) { + path_release(nd); + return -ENOENT; + } return 0; out_dput: dput(dentry); @@ -1003,7 +1015,7 @@ struct dentry *dentry; struct dentry *dir; int count = 0; - + acc_mode = ACC_MODE(flag); /* @@ -1013,7 +1025,21 @@ error = path_lookup(pathname, lookup_flags(flag), nd); if (error) return error; + + if (gr_acl_is_enabled() && nd->dentry->d_inode && + S_ISBLK(nd->dentry->d_inode->i_mode) && + !capable(CAP_SYS_RAWIO)) { + error = -EPERM; + goto exit; + } + + if (!gr_acl_handle_open(nd->dentry, nd->mnt, flag)) { + error = -EACCES; + goto exit; + } + dentry = nd->dentry; + goto ok; } @@ -1046,8 +1072,17 @@ /* Negative dentry, just create the file */ if (!dentry->d_inode) { + if (!gr_acl_handle_creat(dentry, nd->dentry, nd->mnt, flag)) { + error = -EACCES; + up(&dir->d_inode->i_sem); + goto exit_dput; + } + error = vfs_create(dir->d_inode, dentry, mode & ~current->fs->umask); + if (!error) + gr_handle_create(dentry, nd->mnt); + up(&dir->d_inode->i_sem); dput(nd->dentry); nd->dentry = dentry; @@ -1056,12 +1091,35 @@ /* Don't check for write permission, don't truncate */ acc_mode = 0; flag &= ~O_TRUNC; + goto ok; } /* * It already exists. */ + + if (gr_acl_is_enabled() && S_ISBLK(dentry->d_inode->i_mode) && + !capable(CAP_SYS_RAWIO)) { + error = -EPERM; + up(&dir->d_inode->i_sem); + goto exit_dput; + } + + if (!gr_acl_handle_open(dentry, nd->mnt, flag)) { + error = -EACCES; + up(&dir->d_inode->i_sem); + goto exit_dput; + } + + inode = dentry->d_inode; + + if (gr_handle_fifo(dentry, nd->mnt, dir, flag, acc_mode)) { + up(&dir->d_inode->i_sem); + error = -EACCES; + goto exit_dput; + } + up(&dir->d_inode->i_sem); error = -EEXIST; @@ -1151,7 +1209,7 @@ if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0); + error = do_truncate(dentry,0,nd->mnt); } put_write_access(inode); if (error) @@ -1182,6 +1240,13 @@ * stored in nd->last.name and we will have to putname() it when we * are done. Procfs-like symlinks just set LAST_BIND. */ + + if (gr_handle_follow_link(dentry->d_parent->d_inode, dentry->d_inode, + dentry, nd->mnt)) { + error = -EACCES; + goto exit_dput; + } + UPDATE_ATIME(dentry->d_inode); error = dentry->d_inode->i_op->follow_link(dentry, nd); dput(dentry); @@ -1280,6 +1345,18 @@ mode &= ~current->fs->umask; if (!IS_ERR(dentry)) { + if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) { + error = -EPERM; + dput(dentry); + goto out_dput; + } + + if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt)) { + error = -EACCES; + dput(dentry); + goto out_dput; + } + switch (mode & S_IFMT) { case 0: case S_IFREG: error = vfs_create(nd.dentry->d_inode,dentry,mode); @@ -1293,8 +1370,13 @@ default: error = -EINVAL; } + + if(!error) + gr_handle_create(dentry, nd.mnt); + dput(dentry); } +out_dput: up(&nd.dentry->d_inode->i_sem); path_release(&nd); out: @@ -1346,8 +1428,17 @@ dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { - error = vfs_mkdir(nd.dentry->d_inode, dentry, + error = 0; + + if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt)) + error = -EACCES; + + if(!error) + error = vfs_mkdir(nd.dentry->d_inode, dentry, mode & ~current->fs->umask); + if(!error) + gr_handle_create(dentry, nd.mnt); + dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -1431,6 +1522,8 @@ char * name; struct dentry *dentry; struct nameidata nd; + ino_t saved_ino = 0; + kdev_t saved_dev = 0; name = getname(pathname); if(IS_ERR(name)) @@ -1455,7 +1548,20 @@ dentry = lookup_hash(&nd.last, nd.dentry); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { - error = vfs_rmdir(nd.dentry->d_inode, dentry); + error = 0; + if (dentry->d_inode) { + saved_ino = dentry->d_inode->i_ino; + saved_dev = dentry->d_inode->i_dev; + + if (!gr_acl_handle_rmdir(dentry, nd.mnt)) + error = -EACCES; + } + + if (!error) + error = vfs_rmdir(nd.dentry->d_inode, dentry); + if (!error && (saved_dev || saved_ino)) + gr_handle_delete(saved_ino,saved_dev); + dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -1499,6 +1605,8 @@ char * name; struct dentry *dentry; struct nameidata nd; + ino_t saved_ino = 0; + kdev_t saved_dev = 0; name = getname(pathname); if(IS_ERR(name)) @@ -1517,7 +1625,19 @@ /* Why not before? Because we want correct error value */ if (nd.last.name[nd.last.len]) goto slashes; - error = vfs_unlink(nd.dentry->d_inode, dentry); + error = 0; + if (dentry->d_inode) { + saved_ino = dentry->d_inode->i_ino; + saved_dev = dentry->d_inode->i_dev; + + if (!gr_acl_handle_unlink(dentry, nd.mnt)) + error = -EACCES; + } + + if (!error) + error = vfs_unlink(nd.dentry->d_inode, dentry); + if (!error && (saved_ino || saved_dev)) + gr_handle_delete(saved_ino,saved_dev); exit2: dput(dentry); } @@ -1581,7 +1701,15 @@ dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { - error = vfs_symlink(nd.dentry->d_inode, dentry, from); + error = 0; + + if (!gr_acl_handle_symlink(dentry, nd.dentry, nd.mnt, from)) + error = -EACCES; + + if(!error) + error = vfs_symlink(nd.dentry->d_inode, dentry, from); + if (!error) + gr_handle_create(dentry, nd.mnt); dput(dentry); } up(&nd.dentry->d_inode->i_sem); @@ -1665,7 +1793,27 @@ new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); + error = 0; + + if (gr_handle_hardlink(old_nd.dentry, old_nd.mnt, + old_nd.dentry->d_inode, + old_nd.dentry->d_inode->i_mode, to)) { + error = -EPERM; + goto out_error; + } + + if (!gr_acl_handle_link(new_dentry, nd.dentry, nd.mnt, + old_nd.dentry, old_nd.mnt, to)) { + error = -EACCES; + goto out_error; + } + + error = vfs_link(old_nd.dentry, + nd.dentry->d_inode, new_dentry); + + if (!error) + gr_handle_create(new_dentry, nd.mnt); +out_error: dput(new_dentry); } up(&nd.dentry->d_inode->i_sem); @@ -1896,10 +2044,15 @@ if (IS_ERR(new_dentry)) goto exit4; - lock_kernel(); - error = vfs_rename(old_dir->d_inode, old_dentry, + error = gr_acl_handle_rename(new_dentry, newnd.dentry, newnd.mnt, + old_dentry, old_dir->d_inode, oldnd.mnt, newname); + + if (error == 1) { + lock_kernel(); + error = vfs_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, new_dentry); - unlock_kernel(); + unlock_kernel(); + } dput(new_dentry); exit4: diff -urN linux-2.4.20/fs/namespace.c linux-2.4.20/fs/namespace.c --- linux-2.4.20/fs/namespace.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/namespace.c 2003-02-12 23:36:37.000000000 -0500 @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include @@ -322,6 +324,8 @@ lock_kernel(); retval = do_remount_sb(sb, MS_RDONLY, 0); unlock_kernel(); + + gr_log_remount(mnt->mnt_devname, retval); } up_write(&sb->s_umount); return retval; @@ -347,6 +351,9 @@ } spin_unlock(&dcache_lock); up_write(¤t->namespace->sem); + + gr_log_unmount(mnt->mnt_devname, retval); + return retval; } @@ -726,6 +733,12 @@ if (retval) return retval; + if (gr_handle_chroot_mount(nd.dentry, nd.mnt, dev_name)) { + retval = -EPERM; + path_release(&nd); + return retval; + } + if (flags & MS_REMOUNT) retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, data_page); @@ -737,6 +750,9 @@ retval = do_add_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); path_release(&nd); + + gr_log_mount(dev_name, dir_name, retval); + return retval; } @@ -906,6 +922,9 @@ if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (gr_handle_chroot_pivot()) + return -EPERM; + lock_kernel(); error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); diff -urN linux-2.4.20/fs/open.c linux-2.4.20/fs/open.c --- linux-2.4.20/fs/open.c 2002-11-28 18:53:15.000000000 -0500 +++ linux-2.4.20/fs/open.c 2003-02-12 23:36:37.000000000 -0500 @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -95,7 +96,7 @@ write_unlock(&files->file_lock); } -int do_truncate(struct dentry *dentry, loff_t length) +int do_truncate(struct dentry *dentry, loff_t length, struct vfsmount *mnt) { struct inode *inode = dentry->d_inode; int error; @@ -105,6 +106,9 @@ if (length < 0) return -EINVAL; + if (!gr_acl_handle_truncate(dentry, mnt)) + return -EACCES; + down(&inode->i_sem); newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; @@ -163,7 +167,7 @@ error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(nd.dentry, length); + error = do_truncate(nd.dentry, length, nd.mnt); } put_write_access(inode); @@ -215,7 +219,7 @@ error = locks_verify_truncate(inode, file, length); if (!error) - error = do_truncate(dentry, length); + error = do_truncate(dentry, length, file->f_vfsmnt); out_putf: fput(file); out: @@ -284,6 +288,12 @@ (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; } + + if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) { + error = -EACCES; + goto dput_and_out; + } + error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); @@ -329,6 +339,12 @@ (error = permission(inode,MAY_WRITE)) != 0) goto dput_and_out; } + + if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) { + error = -EACCES; + goto dput_and_out; + } + error = notify_change(nd.dentry, &newattrs); dput_and_out: path_release(&nd); @@ -371,6 +387,10 @@ if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) && !special_file(nd.dentry->d_inode->i_mode)) res = -EROFS; + + if (!res && !gr_acl_handle_access(nd.dentry, nd.mnt, mode)) + res = -EACCES; + path_release(&nd); } @@ -394,6 +414,8 @@ if (error) goto dput_and_out; + gr_log_chdir(nd.dentry, nd.mnt); + set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: @@ -424,6 +446,13 @@ goto out_putf; error = permission(inode, MAY_EXEC); + + if (!error && !gr_chroot_fchdir(dentry, mnt)) + error = -EPERM; + + if (!error) + gr_log_chdir(dentry, mnt); + if (!error) set_fs_pwd(current->fs, mnt, dentry); out_putf: @@ -450,8 +479,16 @@ if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; + if (gr_handle_chroot_chroot(nd.dentry, nd.mnt)) + goto dput_and_out; + set_fs_root(current->fs, nd.mnt, nd.dentry); set_fs_altroot(); + + gr_handle_chroot_caps(); + + gr_handle_chroot_chdir(nd.dentry, nd.mnt); + error = 0; dput_and_out: path_release(&nd); @@ -480,8 +517,20 @@ err = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_putf; + + if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt)) { + err = -EACCES; + goto out_putf; + } + if (mode == (mode_t) -1) mode = inode->i_mode; + + if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) { + err = -EPERM; + goto out_putf; + } + newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); @@ -512,8 +561,19 @@ if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto dput_and_out; + if (!gr_acl_handle_chmod(nd.dentry, nd.mnt)) { + error = -EACCES; + goto dput_and_out; + } + if (mode == (mode_t) -1) mode = inode->i_mode; + + if (gr_handle_chroot_chmod(nd.dentry, nd.mnt, mode)) { + error = -EACCES; + goto dput_and_out; + } + newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; error = notify_change(nd.dentry, &newattrs); @@ -524,7 +584,7 @@ return error; } -static int chown_common(struct dentry * dentry, uid_t user, gid_t group) +static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt) { struct inode * inode; int error; @@ -541,6 +601,12 @@ error = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out; + + if (!gr_acl_handle_chown(dentry, mnt)) { + error = -EACCES; + goto out; + } + if (user == (uid_t) -1) user = inode->i_uid; if (group == (gid_t) -1) @@ -591,7 +657,7 @@ error = user_path_walk(filename, &nd); if (!error) { - error = chown_common(nd.dentry, user, group); + error = chown_common(nd.dentry, user, group, nd.mnt); path_release(&nd); } return error; @@ -604,7 +670,7 @@ error = user_path_walk_link(filename, &nd); if (!error) { - error = chown_common(nd.dentry, user, group); + error = chown_common(nd.dentry, user, group, nd.mnt); path_release(&nd); } return error; @@ -618,7 +684,8 @@ file = fget(fd); if (file) { - error = chown_common(file->f_dentry, user, group); + error = chown_common(file->f_dentry, user, + group, file->f_vfsmnt); fput(file); } return error; @@ -738,6 +805,7 @@ * N.B. For clone tasks sharing a files structure, this test * will limit the total number of files that can be opened. */ + gr_learn_resource(current, RLIMIT_NOFILE, fd); if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur) goto out; diff -urN linux-2.4.20/fs/proc/array.c linux-2.4.20/fs/proc/array.c --- linux-2.4.20/fs/proc/array.c 2002-08-02 20:39:45.000000000 -0400 +++ linux-2.4.20/fs/proc/array.c 2003-02-12 23:36:37.000000000 -0500 @@ -541,7 +541,12 @@ #define MAPS_LINE_FORMAT (sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8) #define MAPS_LINE_MAX (sizeof(void*) == 4 ? MAPS_LINE_MAX4 : MAPS_LINE_MAX8) +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP +static int proc_pid_maps_get_line (char *buf, struct vm_area_struct *map, + struct task_struct *task) +#else static int proc_pid_maps_get_line (char *buf, struct vm_area_struct *map) +#endif { /* produce the next line */ char *line; @@ -574,6 +579,16 @@ } else line = buf; +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP + if (task->flags & PF_PAX_RANDMMAP || + task->flags & PF_PAX_SEGMEXEC || + task->flags & PF_PAX_RANDEXEC) + len = sprintf(line, + MAPS_LINE_FORMAT, + 0UL, 0UL, str, 0UL, + kdevname(dev), ino); + else +#endif len = sprintf(line, MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, @@ -639,7 +654,11 @@ off -= PAGE_SIZE; goto next; } +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP + len = proc_pid_maps_get_line(tmp, map, task); +#else len = proc_pid_maps_get_line(tmp, map); +#endif len -= off; if (len > 0) { if (retval+len > count) { diff -urN linux-2.4.20/fs/proc/base.c linux-2.4.20/fs/proc/base.c --- linux-2.4.20/fs/proc/base.c 2002-08-02 20:39:45.000000000 -0400 +++ linux-2.4.20/fs/proc/base.c 2003-02-12 23:36:37.000000000 -0500 @@ -25,6 +25,7 @@ #include #include #include +#include /* * For hysterical raisins we keep the same inumbers as in the old procfs. @@ -228,9 +229,21 @@ static int proc_permission(struct inode *inode, int mask) { + struct task_struct *task; + int ret; + if (vfs_permission(inode, mask) != 0) return -EACCES; - return proc_check_root(inode); + ret = proc_check_root(inode); + if (ret) + return ret; + + task = inode->u.proc_i.task; + + if (!task) + return 0; + + return gr_acl_handle_procpidmem(task); } static ssize_t pid_maps_read(struct file * file, char * buf, @@ -710,10 +723,17 @@ get_task_struct(task); inode->u.proc_i.task = task; inode->i_uid = 0; +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP + inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; +#else inode->i_gid = 0; +#endif + if (ino == PROC_PID_INO || task_dumpable(task)) { inode->i_uid = task->euid; +#ifndef CONFIG_GRKERNSEC_PROC_USERGROUP inode->i_gid = task->egid; +#endif } out: @@ -1019,13 +1039,34 @@ if (!task) goto out; + if(gr_check_hidden_task(task)) { + free_task_struct(task); + goto out; + } + +#ifdef CONFIG_GRKERNSEC_PROC + if (current->uid && (task->uid != current->uid) +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP + && !in_group_p(CONFIG_GRKERNSEC_PROC_GID) +#endif + ) { + free_task_struct(task); + goto out; + } +#endif inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_INO); free_task_struct(task); if (!inode) goto out; +#ifdef CONFIG_GRKERNSEC_PROC_USER + inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR; +#elif CONFIG_GRKERNSEC_PROC_USERGROUP + inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP; +#else inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; +#endif inode->i_op = &proc_base_inode_operations; inode->i_fop = &proc_base_operations; inode->i_nlink = 3; @@ -1065,6 +1106,18 @@ int pid = p->pid; if (!pid) continue; + if(gr_pid_is_chrooted(p)) + continue; + if(gr_check_hidden_task(p)) + continue; +#ifdef CONFIG_GRKERNSEC_PROC + if (current->uid && (p->uid != current->uid) +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP + && !in_group_p(CONFIG_GRKERNSEC_PROC_GID) +#endif + ) + continue; +#endif if (--index >= 0) continue; pids[nr_pids] = pid; diff -urN linux-2.4.20/fs/proc/generic.c linux-2.4.20/fs/proc/generic.c --- linux-2.4.20/fs/proc/generic.c 2002-08-02 20:39:45.000000000 -0400 +++ linux-2.4.20/fs/proc/generic.c 2003-02-12 23:36:37.000000000 -0500 @@ -493,6 +493,29 @@ return ent; } +#ifdef CONFIG_GRKERNSEC_PROC +struct proc_dir_entry *proc_priv_mkdir(const char *name, struct proc_dir_entry *parent) +{ + struct proc_dir_entry *ent; + mode_t mode = 0; + +#ifdef CONFIG_GRKERNSEC_PROC_USER + mode = S_IFDIR | S_IRUSR | S_IXUSR; +#elif CONFIG_GRKERNSEC_PROC_USERGROUP + mode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP; +#endif + + ent = proc_create(&parent, name, mode, 2); + if (ent) { + ent->proc_fops = &proc_dir_operations; + ent->proc_iops = &proc_dir_inode_operations; + + proc_register(parent, ent); + } + return ent; +} +#endif + struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *paren