--- /dev/null
+diff -urN linux-2.4.21/Documentation/Configure.help linux-2.4.21/Documentation/Configure.help
+--- linux-2.4.21/Documentation/Configure.help 2003-06-23 11:42:34.000000000 -0400
++++ linux-2.4.21/Documentation/Configure.help 2003-06-23 11:49:15.000000000 -0400
+@@ -2609,6 +2609,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
+@@ -21729,6 +21743,612 @@
+
+ "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
++ <http://grsecurity.net/features.htm> and read about each option.
++ 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
++ mprotect restrictions
++ removal of /proc/<pid>/[maps|mem]
++ kernel stack randomization
++ mount/unmount/remount logging
++ kernel symbol hiding
++
++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.
++
++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.
++ There are a few video cards that require write access to the BIOS,
++ one of which is the Savage. If you have this video card, you must say
++ N here, or Xfree86 will not function.
++ It is highly recommended that you say Y here if you meet all the
++ conditions above.
++
++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.
++
++Hide kernel symbols
++CONFIG_GRKERNSEC_HIDESYM
++ If you say Y here, getting information on loaded modules, and
++ displaying all kernel symbols through a syscall will be restricted
++ to users with CAP_SYS_MODULE. This option is only effective
++ provided the following conditions are met:
++ 1) The kernel using grsecurity is not precompiled by some distribution
++ 2) You are using the ACL system and hiding other files such as your
++ kernel image and System.map
++ 3) You have the additional /proc restrictions enabled, which removes
++ /proc/kcore
++ If the above conditions are met, this option will aid to provide a
++ useful protection against local and remote kernel exploitation of
++ overflows and arbitrary read/write vulnerabilities.
++
++/proc/<pid>/ipaddr support
++CONFIG_GRKERNSEC_PROC_IPADDR
++ If you say Y here, a new entry will be added to each /proc/<pid>
++ directory that contains the IP address of the person using the task.
++ The IP is carried across local TCP and AF_UNIX stream sockets.
++ This information can be useful for IDS/IPSes to perform remote response
++ to a local attack. The entry is readable by only the owner of the
++ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via
++ the RBAC system), and thus does not create privacy concerns.
++
++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.
++
++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.
++
++Enforce RLIMIT_NPROC on execs
++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.
++
++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.21/Makefile linux-2.4.21/Makefile
+--- linux-2.4.21/Makefile 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/Makefile 2003-06-23 11:49:15.000000000 -0400
+@@ -123,9 +123,10 @@
+ CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
+ NETWORKS =net/network.o
+ CRYPTO =crypto/crypto.o
++GRSECURITY =grsecurity/grsec.o
+
+ LIBS =$(TOPDIR)/lib/lib.a
+-SUBDIRS =kernel drivers mm fs net ipc lib crypto
++SUBDIRS =kernel drivers mm fs net ipc lib crypto grsecurity
+
+ DRIVERS-n :=
+ DRIVERS-y :=
+@@ -265,7 +266,7 @@
+
+ export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL
+
+-export NETWORKS CRYPTO DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
++export NETWORKS CRYPTO 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) \
+ $(CRYPTO) \
++ $(GRSECURITY) \
+ $(LIBS) \
+ --end-group \
+ -o vmlinux
+diff -urN linux-2.4.21/arch/alpha/config.in linux-2.4.21/arch/alpha/config.in
+--- linux-2.4.21/arch/alpha/config.in 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/alpha/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -444,3 +444,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.21/arch/alpha/kernel/osf_sys.c linux-2.4.21/arch/alpha/kernel/osf_sys.c
+--- linux-2.4.21/arch/alpha/kernel/osf_sys.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/alpha/kernel/osf_sys.c 2003-06-23 11:49:15.000000000 -0400
+@@ -33,6 +33,7 @@
+ #include <linux/file.h>
+ #include <linux/types.h>
+ #include <linux/ipc.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/fpu.h>
+ #include <asm/io.h>
+@@ -240,6 +246,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.21/arch/alpha/kernel/ptrace.c linux-2.4.21/arch/alpha/kernel/ptrace.c
+--- linux-2.4.21/arch/alpha/kernel/ptrace.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/alpha/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/user.h>
+ #include <linux/slab.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -275,6 +276,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.21/arch/arm/config.in linux-2.4.21/arch/arm/config.in
+--- linux-2.4.21/arch/arm/config.in 2003-06-23 11:42:30.000000000 -0400
++++ linux-2.4.21/arch/arm/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/cris/config.in linux-2.4.21/arch/cris/config.in
+--- linux-2.4.21/arch/cris/config.in 2003-06-23 11:42:34.000000000 -0400
++++ linux-2.4.21/arch/cris/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -263,3 +263,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.21/arch/i386/config.in linux-2.4.21/arch/i386/config.in
+--- linux-2.4.21/arch/i386/config.in 2003-06-23 11:42:23.000000000 -0400
++++ linux-2.4.21/arch/i386/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -485,3 +485,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.21/arch/i386/kernel/i387.c linux-2.4.21/arch/i386/kernel/i387.c
+--- linux-2.4.21/arch/i386/kernel/i387.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/i386/kernel/i387.c 2003-06-23 11:49:15.000000000 -0400
+@@ -373,13 +373,16 @@
+
+ static inline int restore_i387_fxsave( struct _fpstate *buf )
+ {
++ int err;
+ struct task_struct *tsk = current;
+ clear_fpu( tsk );
+- if ( __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
+- sizeof(struct i387_fxsave_struct) ) )
+- return 1;
++ err = __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
++ sizeof(struct i387_fxsave_struct) );
+ /* mxcsr bit 6 and 31-16 must be zero for security reasons */
+ tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
++ if (err)
++ return 1;
++
+ return convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf );
+ }
+
+diff -urN linux-2.4.21/arch/i386/kernel/ioport.c linux-2.4.21/arch/i386/kernel/ioport.c
+--- linux-2.4.21/arch/i386/kernel/ioport.c 2003-06-23 11:42:23.000000000 -0400
++++ linux-2.4.21/arch/i386/kernel/ioport.c 2003-06-23 11:49:15.000000000 -0400
+@@ -14,6 +14,7 @@
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/stddef.h>
++#include <linux/grsecurity.h>
+
+ /* 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(),
+@@ -109,8 +118,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.21/arch/i386/kernel/ptrace.c linux-2.4.21/arch/i386/kernel/ptrace.c
+--- linux-2.4.21/arch/i386/kernel/ptrace.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/i386/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <linux/errno.h>
+ #include <linux/ptrace.h>
+ #include <linux/user.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -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.21/arch/i386/kernel/sys_i386.c linux-2.4.21/arch/i386/kernel/sys_i386.c
+--- linux-2.4.21/arch/i386/kernel/sys_i386.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/i386/kernel/sys_i386.c 2003-06-23 11:49:15.000000000 -0400
+@@ -18,6 +18,7 @@
+ #include <linux/mman.h>
+ #include <linux/file.h>
+ #include <linux/utsname.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/ipc.h>
+@@ -55,8 +61,14 @@
+ goto out;
+ }
+
++ if(gr_handle_mmap(file, prot)) {
++ fput(file);
++ error = -EACCES;
++ goto out;
++ }
++
+ down_write(&mm->mmap_sem);
+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
+ up_write(&mm->mmap_sem);
+
+ if (file)
+diff -urN linux-2.4.21/arch/ia64/config.in linux-2.4.21/arch/ia64/config.in
+--- linux-2.4.21/arch/ia64/config.in 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/ia64/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -290,3 +290,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.21/arch/ia64/kernel/ptrace.c linux-2.4.21/arch/ia64/kernel/ptrace.c
+--- linux-2.4.21/arch/ia64/kernel/ptrace.c 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/ia64/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -16,6 +16,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/smp_lock.h>
+ #include <linux/user.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/processor.h>
+@@ -1179,6 +1180,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.21/arch/ia64/kernel/sys_ia64.c linux-2.4.21/arch/ia64/kernel/sys_ia64.c
+--- linux-2.4.21/arch/ia64/kernel/sys_ia64.c 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/ia64/kernel/sys_ia64.c 2003-06-23 11:49:15.000000000 -0400
+@@ -15,6 +15,7 @@
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/highuid.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/shmparam.h>
+ #include <asm/uaccess.h>
+@@ -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(current->mm, file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+diff -urN linux-2.4.21/arch/m68k/config.in linux-2.4.21/arch/m68k/config.in
+--- linux-2.4.21/arch/m68k/config.in 2003-06-23 11:42:29.000000000 -0400
++++ linux-2.4.21/arch/m68k/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -563,3 +563,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.21/arch/mips/config.in linux-2.4.21/arch/mips/config.in
+--- linux-2.4.21/arch/mips/config.in 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/mips/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/mips64/config.in linux-2.4.21/arch/mips64/config.in
+--- linux-2.4.21/arch/mips64/config.in 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/mips64/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/parisc/config.in linux-2.4.21/arch/parisc/config.in
+--- linux-2.4.21/arch/parisc/config.in 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/parisc/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/parisc/kernel/ioctl32.c linux-2.4.21/arch/parisc/kernel/ioctl32.c
+--- linux-2.4.21/arch/parisc/kernel/ioctl32.c 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/parisc/kernel/ioctl32.c 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/parisc/kernel/ptrace.c linux-2.4.21/arch/parisc/kernel/ptrace.c
+--- linux-2.4.21/arch/parisc/kernel/ptrace.c 2003-06-23 11:42:34.000000000 -0400
++++ linux-2.4.21/arch/parisc/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -15,7 +15,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/user.h>
+ #include <linux/personality.h>
+-
++#include <linux/grsecurity.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -119,6 +119,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.21/arch/parisc/kernel/sys_parisc.c linux-2.4.21/arch/parisc/kernel/sys_parisc.c
+--- linux-2.4.21/arch/parisc/kernel/sys_parisc.c 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/parisc/kernel/sys_parisc.c 2003-06-23 11:49:15.000000000 -0400
+@@ -12,6 +12,7 @@
+ #include <linux/mman.h>
+ #include <linux/shm.h>
+ #include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
+
+ int sys_pipe(int *fildes)
+ {
+@@ -104,6 +110,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.21/arch/parisc/kernel/sys_parisc32.c linux-2.4.21/arch/parisc/kernel/sys_parisc32.c
+--- linux-2.4.21/arch/parisc/kernel/sys_parisc32.c 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/parisc/kernel/sys_parisc32.c 2003-06-23 11:49:15.000000000 -0400
+@@ -50,6 +50,7 @@
+ #include <linux/highmem.h>
+ #include <linux/highuid.h>
+ #include <linux/mman.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/types.h>
+ #include <asm/uaccess.h>
+@@ -177,6 +178,11 @@
+ struct file *file;
+ int retval;
+ int i;
++#ifdef CONFIG_GRKERNSEC
++ struct file *old_exec_file;
++ struct acl_subject_label *old_acl;
++ struct rlimit old_rlim[RLIM_NLIMITS];
++#endif
+
+ file = open_exec(filename);
+
+@@ -184,6 +190,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.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+ memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
+
+@@ -209,11 +238,24 @@
+ 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_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
++
+ retval = copy_strings32(bprm.envc, envp, &bprm);
+ if (retval < 0)
+ goto out;
+@@ -222,11 +264,31 @@
+ if (retval < 0)
+ goto out;
+
++#ifdef CONFIG_GRKERNSEC
++ old_acl = current->acl;
++ memcpy(old_rlim, current->rlim, sizeof(old_rlim));
++ old_exec_file = current->exec_file;
++ get_file(file);
++ current->exec_file = file;
++#endif
++
++ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
++
+ retval = search_binary_handler(&bprm,regs);
+- if (retval >= 0)
++ if (retval >= 0) {
++#ifdef CONFIG_GRKERNSEC
++ if (old_exec_file)
++ fput(old_exec_file);
++#endif
+ /* execve success */
+ return retval;
+
++#ifdef CONFIG_GRKERNSEC
++ current->acl = old_acl;
++ memcpy(current->rlim, old_rlim, sizeof(old_rlim));
++ fput(current->exec_file);
++ current->exec_file = old_exec_file;
++#endif
+ out:
+ /* Something went wrong, return the inode and free the argument pages*/
+ allow_write_access(bprm.file);
+diff -urN linux-2.4.21/arch/ppc/config.in linux-2.4.21/arch/ppc/config.in
+--- linux-2.4.21/arch/ppc/config.in 2003-06-23 11:42:28.000000000 -0400
++++ linux-2.4.21/arch/ppc/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -461,3 +461,12 @@
+ bool 'Support for early boot texts over serial port' CONFIG_SERIAL_TEXT_DEBUG
+ 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.21/arch/ppc/kernel/ptrace.c linux-2.4.21/arch/ppc/kernel/ptrace.c
+--- linux-2.4.21/arch/ppc/kernel/ptrace.c 2003-06-23 11:42:28.000000000 -0400
++++ linux-2.4.21/arch/ppc/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -24,6 +24,7 @@
+ #include <linux/errno.h>
+ #include <linux/ptrace.h>
+ #include <linux/user.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/page.h>
+@@ -182,6 +183,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.21/arch/ppc/kernel/syscalls.c linux-2.4.21/arch/ppc/kernel/syscalls.c
+--- linux-2.4.21/arch/ppc/kernel/syscalls.c 2003-06-23 11:42:28.000000000 -0400
++++ linux-2.4.21/arch/ppc/kernel/syscalls.c 2003-06-23 11:49:15.000000000 -0400
+@@ -35,6 +35,7 @@
+ #include <linux/ipc.h>
+ #include <linux/utsname.h>
+ #include <linux/file.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/ipc.h>
+@@ -181,8 +182,14 @@
+ goto out;
+ }
+
++ if (gr_handle_mmap(file, prot)) {
++ fput(file);
++ ret = -EACCES;
++ goto out;
++ }
++
+ down_write(¤t->mm->mmap_sem);
+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+ if (file)
+ fput(file);
+diff -urN linux-2.4.21/arch/ppc64/kernel/ioctl32.c linux-2.4.21/arch/ppc64/kernel/ioctl32.c
+--- linux-2.4.21/arch/ppc64/kernel/ioctl32.c 2003-06-23 11:42:23.000000000 -0400
++++ linux-2.4.21/arch/ppc64/kernel/ioctl32.c 2003-06-23 11:49:15.000000000 -0400
+@@ -1789,7 +1789,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.21/arch/s390/config.in linux-2.4.21/arch/s390/config.in
+--- linux-2.4.21/arch/s390/config.in 2003-06-23 11:42:33.000000000 -0400
++++ linux-2.4.21/arch/s390/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/s390x/config.in linux-2.4.21/arch/s390x/config.in
+--- linux-2.4.21/arch/s390x/config.in 2003-06-23 11:42:34.000000000 -0400
++++ linux-2.4.21/arch/s390x/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/sh/config.in linux-2.4.21/arch/sh/config.in
+--- linux-2.4.21/arch/sh/config.in 2003-06-23 11:42:32.000000000 -0400
++++ linux-2.4.21/arch/sh/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/sparc/boot/Makefile linux-2.4.21/arch/sparc/boot/Makefile
+--- linux-2.4.21/arch/sparc/boot/Makefile 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/sparc/boot/Makefile 2003-06-23 11:49:15.000000000 -0400
+@@ -24,7 +24,7 @@
+
+ BTOBJS := $(HEAD) init/main.o init/version.o init/do_mounts.o
+ BTLIBS := $(CORE_FILES_NO_BTFIX) $(FILESYSTEMS) \
+- $(DRIVERS) $(NETWORKS)
++ $(DRIVERS) $(NETWORKS) $(GRSECURITY)
+
+ # I wanted to make this depend upon BTOBJS so that a parallel
+ # build would work, but this fails because $(HEAD) cannot work
+diff -urN linux-2.4.21/arch/sparc/config.in linux-2.4.21/arch/sparc/config.in
+--- linux-2.4.21/arch/sparc/config.in 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/sparc/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -276,3 +276,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.21/arch/sparc/kernel/ptrace.c linux-2.4.21/arch/sparc/kernel/ptrace.c
+--- linux-2.4.21/arch/sparc/kernel/ptrace.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/sparc/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -17,6 +17,7 @@
+ #include <linux/user.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+@@ -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.21/arch/sparc/kernel/sys_sparc.c linux-2.4.21/arch/sparc/kernel/sys_sparc.c
+--- linux-2.4.21/arch/sparc/kernel/sys_sparc.c 2003-06-23 11:42:24.000000000 -0400
++++ linux-2.4.21/arch/sparc/kernel/sys_sparc.c 2003-06-23 11:49:15.000000000 -0400
+@@ -20,6 +20,7 @@
+ #include <linux/utsname.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/ipc.h>
+@@ -240,6 +253,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.21/arch/sparc64/config.in linux-2.4.21/arch/sparc64/config.in
+--- linux-2.4.21/arch/sparc64/config.in 2003-06-23 11:42:30.000000000 -0400
++++ linux-2.4.21/arch/sparc64/config.in 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/arch/sparc64/kernel/ioctl32.c linux-2.4.21/arch/sparc64/kernel/ioctl32.c
+--- linux-2.4.21/arch/sparc64/kernel/ioctl32.c 2003-06-23 11:42:30.000000000 -0400
++++ linux-2.4.21/arch/sparc64/kernel/ioctl32.c 2003-06-23 11:49:15.000000000 -0400
+@@ -2046,7 +2046,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.21/arch/sparc64/kernel/ptrace.c linux-2.4.21/arch/sparc64/kernel/ptrace.c
+--- linux-2.4.21/arch/sparc64/kernel/ptrace.c 2003-06-23 11:42:30.000000000 -0400
++++ linux-2.4.21/arch/sparc64/kernel/ptrace.c 2003-06-23 11:49:15.000000000 -0400
+@@ -18,6 +18,7 @@
+ #include <linux/user.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/asi.h>
+ #include <asm/pgtable.h>
+@@ -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.21/arch/sparc64/kernel/sys_sparc.c linux-2.4.21/arch/sparc64/kernel/sys_sparc.c
+--- linux-2.4.21/arch/sparc64/kernel/sys_sparc.c 2003-06-23 11:42:30.000000000 -0400
++++ linux-2.4.21/arch/sparc64/kernel/sys_sparc.c 2003-06-23 11:49:15.000000000 -0400
+@@ -24,6 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/ipc.h>
+ #include <linux/personality.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/ipc.h>
+@@ -280,6 +288,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.21/arch/sparc64/kernel/sys_sparc32.c linux-2.4.21/arch/sparc64/kernel/sys_sparc32.c
+--- linux-2.4.21/arch/sparc64/kernel/sys_sparc32.c 2003-06-23 11:42:30.000000000 -0400
++++ linux-2.4.21/arch/sparc64/kernel/sys_sparc32.c 2003-06-23 11:49:15.000000000 -0400
+@@ -51,6 +51,8 @@
+ #include <linux/sysctl.h>
+ #include <linux/dnotify.h>
+ #include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/random.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/types.h>
+ #include <asm/ipc.h>
+@@ -3203,6 +3205,11 @@
+ struct file * file;
+ int retval;
+ int i;
++#ifdef CONFIG_GRKERNSEC
++ struct file *old_exec_file;
++ struct acl_subject_label *old_acl;
++ struct rlimit old_rlim[RLIM_NLIMITS];
++#endif
+
+ bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+ memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
+@@ -3213,6 +3229,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;
+@@ -3233,11 +3263,24 @@
+ 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_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
++
+ retval = copy_strings32(bprm.envc, envp, &bprm);
+ if (retval < 0)
+ goto out;
+@@ -3246,11 +3289,32 @@
+ if (retval < 0)
+ goto out;
+
++#ifdef CONFIG_GRKERNSEC
++ old_acl = current->acl;
++ memcpy(old_rlim, current->rlim, sizeof(old_rlim));
++ old_exec_file = current->exec_file;
++ get_file(file);
++ current->exec_file = file;
++#endif
++
++ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
++
+ retval = search_binary_handler(&bprm, regs);
+- if (retval >= 0)
++ if (retval >= 0) {
++#ifdef CONFIG_GRKERNSEC
++ if (old_exec_file)
++ fput(old_exec_file);
++#endif
+ /* execve success */
+ return retval;
++ }
+
++#ifdef CONFIG_GRKERNSEC
++ current->acl = old_acl;
++ memcpy(current->rlim, old_rlim, sizeof(old_rlim));
++ fput(current->exec_file);
++ current->exec_file = old_exec_file;
++#endif
+ out:
+ /* Something went wrong, return the inode and free the argument pages*/
+ allow_write_access(bprm.file);
+diff -urN linux-2.4.21/arch/x86_64/ia32/ia32_ioctl.c linux-2.4.21/arch/x86_64/ia32/ia32_ioctl.c
+--- linux-2.4.21/arch/x86_64/ia32/ia32_ioctl.c 2003-06-23 11:42:23.000000000 -0400
++++ linux-2.4.21/arch/x86_64/ia32/ia32_ioctl.c 2003-06-23 11:49:15.000000000 -0400
+@@ -1932,7 +1932,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.21/drivers/char/keyboard.c linux-2.4.21/drivers/char/keyboard.c
+--- linux-2.4.21/drivers/char/keyboard.c 2003-07-29 17:57:21.000000000 -0400
++++ linux-2.4.21/drivers/char/keyboard.c 2003-07-29 17:58:19.000000000 -0400
+@@ -549,6 +549,16 @@
+ if ((kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) &&
+ !(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value)))
+ return;
++
++#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
++ {
++ void *func = spec_fn_table[value];
++ if (func == show_state || func == show_ptregs ||
++ func == show_mem)
++ return;
++ }
++#endif
++
+ spec_fn_table[value]();
+ }
+
+diff -urN linux-2.4.21/drivers/char/mem.c linux-2.4.21/drivers/char/mem.c
+--- linux-2.4.21/drivers/char/mem.c 2003-07-29 17:57:21.000000000 -0400
++++ linux-2.4.21/drivers/char/mem.c 2003-07-29 17:58:19.000000000 -0400
+@@ -21,6 +21,7 @@
+ #include <linux/raw.h>
+ #include <linux/tty.h>
+ #include <linux/capability.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -41,6 +42,10 @@
+ #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+ extern void tapechar_init(void);
+ #endif
++
++#ifdef CONFIG_GRKERNSEC
++extern struct file_operations grsec_fops;
++#endif
+
+ static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
+ const char * buf, size_t count, loff_t *ppos)
+@@ -114,6 +119,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 +196,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 +301,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)
+@@ -517,6 +538,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;
+ }
+
+@@ -609,7 +639,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 = {
+@@ -685,6 +714,11 @@
+ case 9:
+ filp->f_op = &urandom_fops;
+ break;
++#ifdef CONFIG_GRKERNSEC
++ case 10:
++ filp->f_op = &grsec_fops;
++ break;
++#endif
+ default:
+ return -ENXIO;
+ }
+@@ -711,7 +745,10 @@
+ {5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
+ {7, "full", S_IRUGO | S_IWUGO, &full_fops},
+ {8, "random", S_IRUGO | S_IWUSR, &random_fops},
+- {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}
++ {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
++#ifdef CONFIG_GRKERNSEC
++ {10,"grsec", S_IRUSR | S_IWUGO, &grsec_fops}
++#endif
+ };
+ int i;
+
+diff -urN linux-2.4.21/drivers/char/random.c linux-2.4.21/drivers/char/random.c
+--- linux-2.4.21/drivers/char/random.c 2003-06-23 11:42:01.000000000 -0400
++++ linux-2.4.21/drivers/char/random.c 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/drivers/char/tty_io.c linux-2.4.21/drivers/char/tty_io.c
+--- linux-2.4.21/drivers/char/tty_io.c 2003-06-23 11:42:01.000000000 -0400
++++ linux-2.4.21/drivers/char/tty_io.c 2003-06-23 11:49:15.000000000 -0400
+@@ -99,7 +99,7 @@
+ #include <linux/vt_kern.h>
+ #include <linux/selection.h>
+ #include <linux/devfs_fs_kernel.h>
+-
++#include <linux/grsecurity.h>
+ #include <linux/kmod.h>
+
+ #ifdef CONFIG_VT
+@@ -1397,7 +1397,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) {
+@@ -1499,7 +1503,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;
+@@ -1537,7 +1545,11 @@
+ if (inode->i_rdev == SYSCONS_DEV ||
+ inode->i_rdev == CONSOLE_DEV) {
+ struct file *f;
++#ifdef CONFIG_GRKERNSEC
++ if (!capable(CAP_SYS_TTY_CONFIG))
++#else
+ if (!suser())
++#endif
+ return -EPERM;
+ spin_lock(&redirect_lock);
+ f = redirect;
+@@ -1589,7 +1601,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.21/drivers/char/vt.c linux-2.4.21/drivers/char/vt.c
+--- linux-2.4.21/drivers/char/vt.c 2003-06-23 11:42:01.000000000 -0400
++++ linux-2.4.21/drivers/char/vt.c 2003-06-23 11:49:15.000000000 -0400
+@@ -32,6 +32,7 @@
+ #include <linux/vt_kern.h>
+ #include <linux/kbd_diacr.h>
+ #include <linux/selection.h>
++#include <linux/grsecurity.h>
+
+ #ifdef CONFIG_FB_COMPAT_XPMAC
+ #include <asm/vc_ioctl.h>
+@@ -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.21/drivers/pci/proc.c linux-2.4.21/drivers/pci/proc.c
+--- linux-2.4.21/drivers/pci/proc.c 2003-06-23 11:42:12.000000000 -0400
++++ linux-2.4.21/drivers/pci/proc.c 2003-06-23 11:49:15.000000000 -0400
+@@ -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.21/fs/binfmt_aout.c linux-2.4.21/fs/binfmt_aout.c
+--- linux-2.4.21/fs/binfmt_aout.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/binfmt_aout.c 2003-06-23 11:49:16.000000000 -0400
+@@ -5,6 +5,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/config.h>
+
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+@@ -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;
+
+diff -urN linux-2.4.21/fs/binfmt_elf.c linux-2.4.21/fs/binfmt_elf.c
+--- linux-2.4.21/fs/binfmt_elf.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/binfmt_elf.c 2003-06-23 11:49:16.000000000 -0400
+@@ -11,6 +11,7 @@
+
+ #include <linux/module.h>
+
++#include <linux/config.h>
+ #include <linux/fs.h>
+ #include <linux/stat.h>
+ #include <linux/sched.h>
+@@ -33,6 +34,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/compiler.h>
+ #include <linux/highmem.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/param.h>
+@@ -1003,8 +1163,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.21/fs/buffer.c linux-2.4.21/fs/buffer.c
+--- linux-2.4.21/fs/buffer.c 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/fs/buffer.c 2003-06-23 11:49:16.000000000 -0400
+@@ -1781,6 +1781,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.21/fs/exec.c linux-2.4.21/fs/exec.c
+--- linux-2.4.21/fs/exec.c 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/fs/exec.c 2003-06-23 11:49:16.000000000 -0400
+@@ -43,6 +43,8 @@
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/mmu_context.h>
++#include <linux/major.h>
++#include <linux/grsecurity.h>
+
+ #ifdef CONFIG_KMOD
+ #include <linux/kmod.h>
+@@ -687,6 +725,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);
+ }
+@@ -752,6 +793,8 @@
+ current->suid = current->euid = current->fsuid = bprm->e_uid;
+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
++ gr_handle_chroot_caps(current);
++
+ if(do_unlock)
+ unlock_kernel();
+ current->keep_capabilities = 0;
+@@ -885,6 +928,11 @@
+ struct file *file;
+ int retval;
+ int i;
++#ifdef CONFIG_GRKERNSEC
++ struct file *old_exec_file;
++ struct acl_subject_label *old_acl;
++ struct rlimit old_rlim[RLIM_NLIMITS];
++#endif
+
+ file = open_exec(filename);
+
+@@ -892,7 +940,21 @@
+ 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 *);
+ memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
+
+ bprm.file = file;
+@@ -916,11 +987,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_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;
+@@ -929,11 +1015,32 @@
+ if (retval < 0)
+ goto out;
+
++#ifdef CONFIG_GRKERNSEC
++ old_acl = current->acl;
++ memcpy(old_rlim, current->rlim, sizeof(old_rlim));
++ old_exec_file = current->exec_file;
++ get_file(file);
++ current->exec_file = file;
++#endif
++
++ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
++
+ retval = search_binary_handler(&bprm,regs);
+- if (retval >= 0)
++ if (retval >= 0) {
++#ifdef CONFIG_GRKERNSEC
++ if (old_exec_file)
++ fput(old_exec_file);
++#endif
+ /* execve success */
+ return retval;
++ }
+
++#ifdef CONFIG_GRKERNSEC
++ current->acl = old_acl;
++ memcpy(current->rlim, old_rlim, sizeof(old_rlim));
++ fput(current->exec_file);
++ current->exec_file = old_exec_file;
++#endif
+ out:
+ /* Something went wrong, return the inode and free the argument pages*/
+ allow_write_access(bprm.file);
+@@ -1090,6 +1234,7 @@
+ if (!is_dumpable(current))
+ 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;
+
+@@ -1109,7 +1254,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.21/fs/fcntl.c linux-2.4.21/fs/fcntl.c
+--- linux-2.4.21/fs/fcntl.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/fcntl.c 2003-06-23 11:49:16.000000000 -0400
+@@ -11,6 +11,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/slab.h>
+ #include <linux/iobuf.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/poll.h>
+ #include <asm/siginfo.h>
+@@ -64,6 +65,8 @@
+ int error;
+ int start;
+
++ gr_learn_resource(current, RLIMIT_NOFILE, orig_start);
++
+ write_lock(&files->file_lock);
+
+ error = -EINVAL;
+@@ -86,6 +89,7 @@
+ }
+
+ error = -EMFILE;
++ gr_learn_resource(current, RLIMIT_NOFILE, newfd);
+ if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
+ goto out;
+
+@@ -141,6 +145,8 @@
+ struct file * file, *tofree;
+ struct files_struct * files = current->files;
+
++ gr_learn_resource(current, RLIMIT_NOFILE, newfd);
++
+ write_lock(&files->file_lock);
+ if (!(file = fcheck(oldfd)))
+ goto out_unlock;
+@@ -448,6 +454,10 @@
+ match = -p->pgrp;
+ if (pid != match)
+ continue;
++ if (gr_check_protected_task(p))
++ continue;
++ if (gr_pid_is_chrooted(p))
++ continue;
+ send_sigio_to_task(p, fown, fd, band);
+ }
+ out:
+diff -urN linux-2.4.21/fs/locks.c linux-2.4.21/fs/locks.c
+--- linux-2.4.21/fs/locks.c 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/fs/locks.c 2003-06-23 11:49:16.000000000 -0400
+@@ -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.21/fs/namei.c linux-2.4.21/fs/namei.c
+--- linux-2.4.21/fs/namei.c 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/fs/namei.c 2003-06-23 11:49:16.000000000 -0400
+@@ -22,6 +22,7 @@
+ #include <linux/dnotify.h>
+ #include <linux/smp_lock.h>
+ #include <linux/personality.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/namei.h>
+ #include <asm/uaccess.h>
+@@ -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);
+@@ -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,7 +1072,16 @@
+ if (!dentry->d_inode) {
+ if (!IS_POSIXACL(dir->d_inode))
+ mode &= ~current->fs->umask;
++ if (!gr_acl_handle_creat(dentry, nd->dentry, nd->mnt, flag, mode)) {
++ error = -EACCES;
++ up(&dir->d_inode->i_sem);
++ goto exit_dput;
++ }
++
+ error = vfs_create(dir->d_inode, dentry, mode);
++ 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, mode)) {
++ 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,7 +1428,16 @@
+ if (!IS_ERR(dentry)) {
+ if (!IS_POSIXACL(nd.dentry->d_inode))
+ mode &= ~current->fs->umask;
+- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
++ 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);
++ 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,22 @@
+ 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) {
++ if (dentry->d_inode->i_nlink <= 1) {
++ 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 +1607,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 +1627,21 @@
+ /* 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) {
++ if (dentry->d_inode->i_nlink <= 1) {
++ 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 +1705,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 +1797,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 +2048,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.21/fs/namespace.c linux-2.4.21/fs/namespace.c
+--- linux-2.4.21/fs/namespace.c 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/fs/namespace.c 2003-06-23 11:49:16.000000000 -0400
+@@ -15,6 +15,8 @@
+ #include <linux/quotaops.h>
+ #include <linux/acct.h>
+ #include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+
+@@ -325,6 +327,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;
+@@ -350,6 +354,9 @@
+ }
+ spin_unlock(&dcache_lock);
+ up_write(¤t->namespace->sem);
++
++ gr_log_unmount(mnt->mnt_devname, retval);
++
+ return retval;
+ }
+
+@@ -729,6 +736,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);
+@@ -740,6 +753,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;
+ }
+
+@@ -909,6 +925,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.21/fs/open.c linux-2.4.21/fs/open.c
+--- linux-2.4.21/fs/open.c 2003-06-23 11:41:28.000000000 -0400
++++ linux-2.4.21/fs/open.c 2003-06-23 11:49:16.000000000 -0400
+@@ -15,6 +15,7 @@
+ #include <linux/slab.h>
+ #include <linux/tty.h>
+ #include <linux/iobuf.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+
+@@ -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(current);
++
++ 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, mode)) {
++ 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, mode)) {
++ 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.21/fs/proc/array.c linux-2.4.21/fs/proc/array.c
+--- linux-2.4.21/fs/proc/array.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/proc/array.c 2003-06-23 11:49:16.000000000 -0400
+@@ -334,6 +340,12 @@
+
+ wchan = get_wchan(task);
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ wchan = 0;
++ eip = 0;
++ esp = 0;
++#endif
++
+ collect_sigign_sigcatch(task, &sigign, &sigcatch);
+
+ /* scale priority and nice values from timeslices to -20..20 */
+@@ -684,6 +727,16 @@
+ return retval;
+ }
+
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++int proc_pid_ipaddr(struct task_struct *task, char * buffer)
++{
++ int len;
++
++ len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->curr_ip));
++ return len;
++}
++#endif
++
+ #ifdef CONFIG_SMP
+ int proc_pid_cpu(struct task_struct *task, char * buffer)
+ {
+diff -urN linux-2.4.21/fs/proc/base.c linux-2.4.21/fs/proc/base.c
+--- linux-2.4.21/fs/proc/base.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/proc/base.c 2003-06-23 11:49:16.000000000 -0400
+@@ -25,6 +25,7 @@
+ #include <linux/string.h>
+ #include <linux/seq_file.h>
+ #include <linux/namespace.h>
++#include <linux/grsecurity.h>
+
+ /*
+ * For hysterical raisins we keep the same inumbers as in the old procfs.
+@@ -41,6 +42,9 @@
+ int proc_pid_status(struct task_struct*,char*);
+ int proc_pid_statm(struct task_struct*,char*);
+ int proc_pid_cpu(struct task_struct*,char*);
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++int proc_pid_ipaddr(struct task_struct*,char*);
++#endif
+
+ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+ {
+@@ -228,9 +232,22 @@
+
+ static int proc_permission(struct inode *inode, int mask)
+ {
++ int ret;
++ struct task_struct *task;
++
+ 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,
+@@ -546,6 +563,9 @@
+ PROC_PID_STATM,
+ PROC_PID_MAPS,
+ PROC_PID_CPU,
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++ PROC_PID_IPADDR,
++#endif
+ PROC_PID_MOUNTS,
+ PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
+ };
+@@ -561,6 +581,9 @@
+ #ifdef CONFIG_SMP
+ E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO),
+ #endif
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++ E(PROC_PID_IPADDR, "ipaddr", S_IFREG|S_IRUSR),
++#endif
+ E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO),
+ E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+ E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
+@@ -717,10 +740,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:
+@@ -928,6 +958,12 @@
+ inode->u.proc_i.op.proc_read = proc_pid_cpu;
+ break;
+ #endif
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
++ case PROC_PID_IPADDR:
++ inode->i_fop = &proc_info_file_operations;
++ inode->u.proc_i.op.proc_read = proc_pid_ipaddr;
++ break;
++#endif
+ case PROC_PID_MEM:
+ inode->i_op = &proc_mem_inode_operations;
+ inode->i_fop = &proc_mem_operations;
+@@ -1026,13 +1062,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;
+@@ -1072,6 +1129,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.21/fs/proc/generic.c linux-2.4.21/fs/proc/generic.c
+--- linux-2.4.21/fs/proc/generic.c 2003-07-29 17:57:01.000000000 -0400
++++ linux-2.4.21/fs/proc/generic.c 2003-07-29 17:58:19.000000000 -0400
+@@ -503,6 +503,32 @@
+ 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;
++
++ if (proc_register(parent, ent) < 0) {
++ kfree(ent);
++ ent = NULL;
++ }
++ }
++ return ent;
++}
++#endif
++
+ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
+ struct proc_dir_entry *parent)
+ {
+diff -urN linux-2.4.21/fs/proc/inode.c linux-2.4.21/fs/proc/inode.c
+--- linux-2.4.21/fs/proc/inode.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/proc/inode.c 2003-06-23 11:49:16.000000000 -0400
+@@ -152,7 +152,11 @@
+ if (de->mode) {
+ inode->i_mode = de->mode;
+ inode->i_uid = de->uid;
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
++#else
+ inode->i_gid = de->gid;
++#endif
+ }
+ if (de->size)
+ inode->i_size = de->size;
+diff -urN linux-2.4.21/fs/proc/proc_misc.c linux-2.4.21/fs/proc/proc_misc.c
+--- linux-2.4.21/fs/proc/proc_misc.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/proc/proc_misc.c 2003-06-23 11:49:16.000000000 -0400
+@@ -568,6 +568,7 @@
+ void __init proc_misc_init(void)
+ {
+ struct proc_dir_entry *entry;
++ int gr_mode = 0;
+ static struct {
+ char *name;
+ int (*read_proc)(char*,char**,off_t,int,int*,void*);
+@@ -582,48 +583,81 @@
+ #ifdef CONFIG_STRAM_PROC
+ {"stram", stram_read_proc},
+ #endif
+-#ifdef CONFIG_MODULES
++#if defined(CONFIG_MODULES) && !defined(CONFIG_GRKERNSEC_PROC)
+ {"modules", modules_read_proc},
+ #endif
+ {"stat", kstat_read_proc},
++#ifndef CONFIG_GRKERNSEC_PROC_ADD
+ {"devices", devices_read_proc},
+-#if !defined(CONFIG_ARCH_S390)
++#endif
++#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_GRKERNSEC_PROC_ADD)
+ {"interrupts", interrupts_read_proc},
+ #endif
+ {"filesystems", filesystems_read_proc},
++#ifndef CONFIG_GRKERNSEC_PROC_ADD
+ {"dma", dma_read_proc},
+ {"ioports", ioports_read_proc},
+ {"cmdline", cmdline_read_proc},
++#endif
+ #ifdef CONFIG_SGI_DS1286
+ {"rtc", ds1286_read_proc},
+ #endif
+ {"locks", locks_read_proc},
+ {"swaps", swaps_read_proc},
++#ifndef CONFIG_GRKERNSEC_PROC_ADD
+ {"iomem", memory_read_proc},
++#endif
+ {"execdomains", execdomains_read_proc},
+ {NULL,}
+ };
+ for (p = simple_ones; p->name; p++)
+ create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
+
++#ifdef CONFIG_GRKERNSEC_PROC_USER
++ gr_mode = S_IRUSR;
++#elif CONFIG_GRKERNSEC_PROC_USERGROUP
++ gr_mode = S_IRUSR | S_IRGRP;
++#endif
++
++#if defined(CONFIG_GRKERNSEC_PROC) && defined(CONFIG_MODULES)
++ create_proc_read_entry("modules", gr_mode, NULL, &modules_read_proc, NULL);
++#endif
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ create_proc_read_entry("devices", gr_mode, NULL, &devices_read_proc, NULL);
++ create_proc_read_entry("dma", gr_mode, NULL, &dma_read_proc, NULL);
++ create_proc_read_entry("ioports", gr_mode, NULL, &ioports_read_proc, NULL);
++ create_proc_read_entry("cmdline", gr_mode, NULL, &cmdline_read_proc, NULL);
++ create_proc_read_entry("iomem", gr_mode, NULL, &memory_read_proc, NULL);
++#if !defined(CONFIG_ARCH_S390)
++ create_proc_read_entry("interrupts", gr_mode, NULL, &interrupts_read_proc, NULL);
++#endif
++#endif
++
+ proc_symlink("mounts", NULL, "self/mounts");
+
+ /* And now for trickier ones */
+ entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
+ if (entry)
+ entry->proc_fops = &proc_kmsg_operations;
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ create_seq_entry("cpuinfo", gr_mode, &proc_cpuinfo_operations);
++ create_seq_entry("slabinfo", gr_mode,&proc_slabinfo_operations);
++#else
+ create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+- create_seq_entry("partitions", 0, &proc_partitions_operations);
+ create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
++#endif
++ create_seq_entry("partitions", 0, &proc_partitions_operations);
+ #ifdef CONFIG_MODULES
+- create_seq_entry("ksyms", 0, &proc_ksyms_operations);
++ create_seq_entry("ksyms", gr_mode, &proc_ksyms_operations);
+ #endif
++#ifndef CONFIG_GRKERNSEC_PROC_ADD
+ proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
+ if (proc_root_kcore) {
+ proc_root_kcore->proc_fops = &proc_kcore_operations;
+ proc_root_kcore->size =
+ (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
+ }
++#endif
+ if (prof_shift) {
+ entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
+ if (entry) {
+diff -urN linux-2.4.21/fs/proc/proc_tty.c linux-2.4.21/fs/proc/proc_tty.c
+--- linux-2.4.21/fs/proc/proc_tty.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/proc/proc_tty.c 2003-06-23 11:49:16.000000000 -0400
+@@ -174,7 +174,11 @@
+ * password lengths and inter-keystroke timings during password
+ * entry.
+ */
++#ifdef CONFIG_GRKERNSEC_PROC
++ proc_tty_driver = proc_priv_mkdir("tty/driver", 0);
++#else
+ proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR | S_IXUSR, 0);
++#endif
+
+ create_proc_read_entry("tty/ldiscs", 0, 0, tty_ldiscs_read_proc,NULL);
+ create_proc_read_entry("tty/drivers", 0, 0, tty_drivers_read_proc,NULL);
+diff -urN linux-2.4.21/fs/proc/root.c linux-2.4.21/fs/proc/root.c
+--- linux-2.4.21/fs/proc/root.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/proc/root.c 2003-06-23 11:49:16.000000000 -0400
+@@ -37,13 +37,21 @@
+ return;
+ }
+ proc_misc_init();
++#ifdef CONFIG_GRKERNSEC_PROC
++ proc_net = proc_priv_mkdir("net", 0);
++#else
+ proc_net = proc_mkdir("net", 0);
++#endif
+ #ifdef CONFIG_SYSVIPC
+ proc_mkdir("sysvipc", 0);
+ #endif
+ #ifdef CONFIG_SYSCTL
++#ifdef CONFIG_GRKERNSEC_PROC
++ proc_sys_root = proc_priv_mkdir("sys", 0);
++#else
+ proc_sys_root = proc_mkdir("sys", 0);
+ #endif
++#endif
+ #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
+ proc_mkdir("sys/fs", 0);
+ proc_mkdir("sys/fs/binfmt_misc", 0);
+@@ -67,7 +75,12 @@
+ #ifdef CONFIG_PPC_RTAS
+ proc_rtas_init();
+ #endif
++
++#ifdef CONFIG_GRKERNSEC_PROC_ADD
++ proc_bus = proc_priv_mkdir("bus", 0);
++#else
+ proc_bus = proc_mkdir("bus", 0);
++#endif
+ }
+
+ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
+diff -urN linux-2.4.21/fs/readdir.c linux-2.4.21/fs/readdir.c
+--- linux-2.4.21/fs/readdir.c 2003-06-23 11:41:29.000000000 -0400
++++ linux-2.4.21/fs/readdir.c 2003-06-23 11:49:16.000000000 -0400
+@@ -10,6 +10,7 @@
+ #include <linux/stat.h>
+ #include <linux/file.h>
+ #include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+
+@@ -181,6 +182,7 @@
+ struct readdir_callback {
+ struct old_linux_dirent * dirent;
+ int count;
++ struct nameidata nd;
+ };
+
+ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
+@@ -191,6 +193,10 @@
+
+ if (buf->count)
+ return -EINVAL;
++
++ if (!gr_acl_handle_filldir(buf->nd.dentry, buf->nd.mnt, ino))
++ return 0;
++
+ buf->count++;
+ dirent = buf->dirent;
+ put_user(ino, &dirent->d_ino);
+@@ -215,6 +221,9 @@
+ buf.count = 0;
+ buf.dirent = dirent;
+
++ buf.nd.dentry = file->f_dentry;
++ buf.nd.mnt = file->f_vfsmnt;
++
+ error = vfs_readdir(file, fillonedir, &buf);
+ if (error >= 0)
+ error = buf.count;
+@@ -242,6 +251,7 @@
+ struct linux_dirent * previous;
+ int count;
+ int error;
++ struct nameidata nd;
+ };
+
+ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
+@@ -254,6 +264,10 @@
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
++
++ if (!gr_acl_handle_filldir(buf->nd.dentry, buf->nd.mnt, ino))
++ return 0;
++
+ dirent = buf->previous;
+ if (dirent)
+ put_user(offset, &dirent->d_off);
+@@ -286,6 +300,9 @@
+ buf.count = count;
+ buf.error = 0;
+
++ buf.nd.dentry = file->f_dentry;
++ buf.nd.mnt = file->f_vfsmnt;
++
+ error = vfs_readdir(file, filldir, &buf);
+ if (error < 0)
+ goto out_putf;
+@@ -320,6 +337,7 @@
+ struct linux_dirent64 * previous;
+ int count;
+ int error;
++ struct nameidata nd;
+ };
+
+ static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
+@@ -332,6 +350,10 @@
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
++
++ if (!gr_acl_handle_filldir(buf->nd.dentry, buf->nd.mnt, ino))
++ return 0;
++
+ dirent = buf->previous;
+ if (dirent) {
+ d.d_off = offset;
+@@ -369,6 +391,9 @@
+ buf.count = count;
+ buf.error = 0;
+
++ buf.nd.mnt = file->f_vfsmnt;
++ buf.nd.dentry = file->f_dentry;
++
+ error = vfs_readdir(file, filldir64, &buf);
+ if (error < 0)
+ goto out_putf;
+diff -urN linux-2.4.21/grsecurity/Config.in linux-2.4.21/grsecurity/Config.in
+--- linux-2.4.21/grsecurity/Config.in 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/Config.in 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,260 @@
++choice 'Security level' \
++ "Low CONFIG_GRKERNSEC_LOW \
++ Medium CONFIG_GRKERNSEC_MID \
++ High CONFIG_GRKERNSEC_HI \
++ Customized CONFIG_GRKERNSEC_CUSTOM" Customized
++if [ "$CONFIG_GRKERNSEC_LOW" = "y" ]; then
++define_bool CONFIG_GRKERNSEC_RANDSRC n
++define_bool CONFIG_GRKERNSEC_RANDRPC n
++define_bool CONFIG_GRKERNSEC_FORKFAIL n
++define_bool CONFIG_GRKERNSEC_TIME n
++define_bool CONFIG_GRKERNSEC_SIGNAL n
++define_bool CONFIG_GRKERNSEC_CHROOT_SHMAT n
++define_bool CONFIG_GRKERNSEC_CHROOT_MOUNT n
++define_bool CONFIG_GRKERNSEC_CHROOT_FCHDIR n
++define_bool CONFIG_GRKERNSEC_CHROOT_DOUBLE n
++define_bool CONFIG_GRKERNSEC_CHROOT_PIVOT n
++define_bool CONFIG_GRKERNSEC_CHROOT_MKNOD n
++define_bool CONFIG_GRKERNSEC_PROC n
++define_bool CONFIG_GRKERNSEC_PROC_IPADDR n
++define_bool CONFIG_GRKERNSEC_HIDESYM n
++define_bool CONFIG_GRKERNSEC_CHROOT_CAPS n
++define_bool CONFIG_GRKERNSEC_CHROOT_SYSCTL n
++define_bool CONFIG_GRKERNSEC_PROC_USERGROUP n
++define_bool CONFIG_GRKERNSEC_KMEM n
++define_bool CONFIG_GRKERNSEC_PROC_ADD n
++define_bool CONFIG_GRKERNSEC_CHROOT_CHMOD n
++define_bool CONFIG_GRKERNSEC_CHROOT_NICE n
++define_bool CONFIG_GRKERNSEC_CHROOT_FINDTASK n
++if [ "$CONFIG_X86" = "y" ]; then
++define_bool CONFIG_GRKERNSEC_IO n
++fi
++define_bool CONFIG_GRKERNSEC_AUDIT_MOUNT n
++define_bool CONFIG_GRKERNSEC_ACL_HIDEKERN n
++define_bool CONFIG_GRKERNSEC_RESLOG n
++define_int CONFIG_GRKERNSEC_ACL_MAXTRIES 3
++define_int CONFIG_GRKERNSEC_ACL_TIMEOUT 30
++
++define_int CONFIG_GRKERNSEC_FLOODTIME 10
++define_int CONFIG_GRKERNSEC_FLOODBURST 4
++define_bool CONFIG_GRKERNSEC_LINK y
++define_bool CONFIG_GRKERNSEC_FIFO y
++define_bool CONFIG_GRKERNSEC_RANDPID y
++define_bool CONFIG_GRKERNSEC_EXECVE y
++define_bool CONFIG_GRKERNSEC_RANDNET y
++define_bool CONFIG_GRKERNSEC_RANDISN n
++define_bool CONFIG_GRKERNSEC_DMESG y
++define_bool CONFIG_GRKERNSEC_RANDID y
++define_bool CONFIG_GRKERNSEC_CHROOT_CHDIR y
++fi
++if [ "$CONFIG_GRKERNSEC_MID" = "y" ]; then
++define_bool CONFIG_GRKERNSEC_KMEM n
++define_bool CONFIG_GRKERNSEC_PROC_IPADDR n
++define_bool CONFIG_GRKERNSEC_HIDESYM n
++define_bool CONFIG_GRKERNSEC_PROC_ADD n
++define_bool CONFIG_GRKERNSEC_CHROOT_CHMOD n
++define_bool CONFIG_GRKERNSEC_CHROOT_NICE n
++define_bool CONFIG_GRKERNSEC_CHROOT_FINDTASK n
++if [ "$CONFIG_X86" = "y" ]; then
++define_bool CONFIG_GRKERNSEC_IO n
++fi
++define_bool CONFIG_GRKERNSEC_AUDIT_MOUNT n
++define_bool CONFIG_GRKERNSEC_CHROOT_CAPS n
++define_bool CONFIG_GRKERNSEC_CHROOT_SYSCTL y
++define_bool CONFIG_GRKERNSEC_AUDIT_MOUNT n
++define_bool CONFIG_GRKERNSEC_CHROOT_FCHDIR n
++define_bool CONFIG_GRKERNSEC_ACL_HIDEKERN n
++define_bool CONFIG_GRKERNSEC_RESLOG n
++define_int CONFIG_GRKERNSEC_ACL_MAXTRIES 3
++define_int CONFIG_GRKERNSEC_ACL_TIMEOUT 30
++
++define_int CONFIG_GRKERNSEC_FLOODTIME 10
++define_int CONFIG_GRKERNSEC_FLOODBURST 4
++define_bool CONFIG_GRKERNSEC_LINK y
++define_bool CONFIG_GRKERNSEC_FIFO y
++define_bool CONFIG_GRKERNSEC_RANDPID y
++define_bool CONFIG_GRKERNSEC_EXECVE y
++define_bool CONFIG_GRKERNSEC_DMESG y
++define_bool CONFIG_GRKERNSEC_RANDID y
++define_bool CONFIG_GRKERNSEC_RANDNET y
++define_bool CONFIG_GRKERNSEC_RANDISN y
++define_bool CONFIG_GRKERNSEC_RANDSRC y
++define_bool CONFIG_GRKERNSEC_RANDRPC y
++define_bool CONFIG_GRKERNSEC_FORKFAIL y
++define_bool CONFIG_GRKERNSEC_TIME y
++define_bool CONFIG_GRKERNSEC_SIGNAL y
++define_bool CONFIG_GRKERNSEC_CHROOT y
++define_bool CONFIG_GRKERNSEC_CHROOT_SHMAT n
++define_bool CONFIG_GRKERNSEC_CHROOT_UNIX y
++define_bool CONFIG_GRKERNSEC_CHROOT_MOUNT y
++define_bool CONFIG_GRKERNSEC_CHROOT_PIVOT y
++define_bool CONFIG_GRKERNSEC_CHROOT_DOUBLE y
++define_bool CONFIG_GRKERNSEC_CHROOT_CHDIR y
++define_bool CONFIG_GRKERNSEC_CHROOT_MKNOD y
++define_bool CONFIG_GRKERNSEC_PROC y
++define_bool CONFIG_GRKERNSEC_PROC_USERGROUP y
++define_int CONFIG_GRKERNSEC_PROC_GID 10
++fi
++if [ "$CONFIG_GRKERNSEC_HI" = "y" ]; then
++define_int CONFIG_GRKERNSEC_FLOODTIME 10
++define_int CONFIG_GRKERNSEC_FLOODBURST 4
++define_bool CONFIG_GRKERNSEC_LINK y
++define_bool CONFIG_GRKERNSEC_FIFO y
++define_bool CONFIG_GRKERNSEC_RANDPID y
++define_bool CONFIG_GRKERNSEC_EXECVE y
++define_bool CONFIG_GRKERNSEC_DMESG y
++define_bool CONFIG_GRKERNSEC_RANDID y
++define_bool CONFIG_GRKERNSEC_RANDSRC y
++define_bool CONFIG_GRKERNSEC_RANDRPC y
++define_bool CONFIG_GRKERNSEC_FORKFAIL y
++define_bool CONFIG_GRKERNSEC_TIME y
++define_bool CONFIG_GRKERNSEC_SIGNAL y
++define_bool CONFIG_GRKERNSEC_CHROOT_SHMAT y
++define_bool CONFIG_GRKERNSEC_CHROOT_UNIX y
++define_bool CONFIG_GRKERNSEC_CHROOT_MOUNT y
++define_bool CONFIG_GRKERNSEC_CHROOT_FCHDIR y
++define_bool CONFIG_GRKERNSEC_CHROOT_PIVOT y
++define_bool CONFIG_GRKERNSEC_CHROOT_DOUBLE y
++define_bool CONFIG_GRKERNSEC_CHROOT_CHDIR y
++define_bool CONFIG_GRKERNSEC_CHROOT_MKNOD y
++define_bool CONFIG_GRKERNSEC_CHROOT_CAPS y
++define_bool CONFIG_GRKERNSEC_CHROOT_SYSCTL y
++define_bool CONFIG_GRKERNSEC_CHROOT_FINDTASK y
++define_bool CONFIG_GRKERNSEC_PROC y
++define_bool CONFIG_GRKERNSEC_PROC_IPADDR n
++define_bool CONFIG_GRKERNSEC_HIDESYM y
++define_bool CONFIG_GRKERNSEC_PROC_USERGROUP y
++define_int CONFIG_GRKERNSEC_PROC_GID 10
++define_bool CONFIG_GRKERNSEC_KMEM y
++define_bool CONFIG_GRKERNSEC_RESLOG y
++define_bool CONFIG_GRKERNSEC_RANDNET y
++define_bool CONFIG_GRKERNSEC_RANDISN y
++
++define_bool CONFIG_GRKERNSEC_AUDIT_MOUNT n
++define_bool CONFIG_GRKERNSEC_ACL_HIDEKERN n
++define_int CONFIG_GRKERNSEC_ACL_MAXTRIES 3
++define_int CONFIG_GRKERNSEC_ACL_TIMEOUT 30
++
++define_bool CONFIG_GRKERNSEC_PROC_ADD y
++define_bool CONFIG_GRKERNSEC_CHROOT_CHMOD y
++define_bool CONFIG_GRKERNSEC_CHROOT_NICE y
++if [ "$CONFIG_X86" = "y" ]; then
++define_bool CONFIG_GRKERNSEC_IO n
++fi
++define_bool CONFIG_GRKERNSEC_AUDIT_MOUNT y
++fi
++if [ "$CONFIG_GRKERNSEC_CUSTOM" = "y" ]; then
++mainmenu_option next_comment
++comment 'Address Space Protection'
++bool 'Deny writing to /dev/kmem, /dev/mem, and /dev/port' CONFIG_GRKERNSEC_KMEM
++if [ "$CONFIG_X86" = "y" ]; then
++ bool 'Disable privileged I/O' CONFIG_GRKERNSEC_IO
++ if [ "$CONFIG_GRKERNSEC_IO" = "y" ]; then
++ define_bool CONFIG_RTC y
++ fi
++fi
++bool 'Hide kernel symbols' CONFIG_GRKERNSEC_HIDESYM
++endmenu
++mainmenu_option next_comment
++comment 'Role Based Access Control Options'
++bool 'Hide kernel processes' CONFIG_GRKERNSEC_ACL_HIDEKERN
++int 'Maximum tries before password lockout' CONFIG_GRKERNSEC_ACL_MAXTRIES 3
++int 'Time to wait after max password tries, in seconds' CONFIG_GRKERNSEC_ACL_TIMEOUT 30
++endmenu
++mainmenu_option next_comment
++comment 'Filesystem Protections'
++bool 'Proc restrictions' CONFIG_GRKERNSEC_PROC
++if [ "$CONFIG_GRKERNSEC_PROC" != "n" ]; then
++ bool ' Restrict to user only' CONFIG_GRKERNSEC_PROC_USER
++ if [ "$CONFIG_GRKERNSEC_PROC_USER" != "y" ]; then
++ bool ' Allow special group' CONFIG_GRKERNSEC_PROC_USERGROUP
++ if [ "$CONFIG_GRKERNSEC_PROC_USERGROUP" != "n" ]; then
++ int ' GID for special group' CONFIG_GRKERNSEC_PROC_GID 1001
++ fi
++ fi
++ if [ "$CONFIG_GRKERNSEC_PROC_USER" != "n" -o "$CONFIG_GRKERNSEC_PROC_USERGROUP" != "n" ]; then
++ bool ' Additional restrictions' CONFIG_GRKERNSEC_PROC_ADD
++ fi
++fi
++bool 'Linking restrictions' CONFIG_GRKERNSEC_LINK
++bool 'FIFO restrictions' CONFIG_GRKERNSEC_FIFO
++bool 'Chroot jail restrictions' CONFIG_GRKERNSEC_CHROOT
++if [ "$CONFIG_GRKERNSEC_CHROOT" != "n" ]; then
++bool ' Deny mounts' CONFIG_GRKERNSEC_CHROOT_MOUNT
++bool ' Deny double-chroots' CONFIG_GRKERNSEC_CHROOT_DOUBLE
++bool ' Deny pivot_root in chroot' CONFIG_GRKERNSEC_CHROOT_PIVOT
++bool ' Enforce chdir("/") on all chroots' CONFIG_GRKERNSEC_CHROOT_CHDIR
++bool ' Deny (f)chmod +s' CONFIG_GRKERNSEC_CHROOT_CHMOD
++bool ' Deny fchdir out of chroot' CONFIG_GRKERNSEC_CHROOT_FCHDIR
++bool ' Deny mknod' CONFIG_GRKERNSEC_CHROOT_MKNOD
++bool ' Deny shmat() out of chroot' CONFIG_GRKERNSEC_CHROOT_SHMAT
++bool ' Deny access to abstract AF_UNIX sockets out of chroot' CONFIG_GRKERNSEC_CHROOT_UNIX
++bool ' Protect outside processes' CONFIG_GRKERNSEC_CHROOT_FINDTASK
++bool ' Restrict priority changes' CONFIG_GRKERNSEC_CHROOT_NICE
++bool ' Deny sysctl writes in chroot' CONFIG_GRKERNSEC_CHROOT_SYSCTL
++bool ' Capability restrictions within chroot' CONFIG_GRKERNSEC_CHROOT_CAPS
++fi
++endmenu
++mainmenu_option next_comment
++comment 'Kernel Auditing'
++bool 'Single group for auditing' CONFIG_GRKERNSEC_AUDIT_GROUP
++if [ "$CONFIG_GRKERNSEC_AUDIT_GROUP" != "n" ]; then
++int ' GID for auditing' CONFIG_GRKERNSEC_AUDIT_GID 1007
++fi
++bool 'Exec logging' CONFIG_GRKERNSEC_EXECLOG
++bool 'Resource logging' CONFIG_GRKERNSEC_RESLOG
++bool 'Log execs within chroot' CONFIG_GRKERNSEC_CHROOT_EXECLOG
++bool 'Chdir logging' CONFIG_GRKERNSEC_AUDIT_CHDIR
++bool '(Un)Mount logging' CONFIG_GRKERNSEC_AUDIT_MOUNT
++bool 'IPC logging' CONFIG_GRKERNSEC_AUDIT_IPC
++bool 'Signal logging' CONFIG_GRKERNSEC_SIGNAL
++bool 'Fork failure logging' CONFIG_GRKERNSEC_FORKFAIL
++bool 'Time change logging' CONFIG_GRKERNSEC_TIME
++bool '/proc/<pid>/ipaddr support' CONFIG_GRKERNSEC_PROC_IPADDR
++endmenu
++mainmenu_option next_comment
++comment 'Executable Protections'
++bool 'Enforce RLIMIT_NPROC on execs' CONFIG_GRKERNSEC_EXECVE
++bool 'Dmesg(8) restriction' CONFIG_GRKERNSEC_DMESG
++bool 'Randomized PIDs' CONFIG_GRKERNSEC_RANDPID
++bool 'Trusted path execution' CONFIG_GRKERNSEC_TPE
++if [ "$CONFIG_GRKERNSEC_TPE" != "n" ]; then
++bool ' Partially restrict non-root users' CONFIG_GRKERNSEC_TPE_ALL
++int ' GID for untrusted users:' CONFIG_GRKERNSEC_TPE_GID 1005
++fi
++endmenu
++mainmenu_option next_comment
++comment 'Network Protections'
++bool 'Larger entropy pools' CONFIG_GRKERNSEC_RANDNET
++bool 'Truly random TCP ISN selection' CONFIG_GRKERNSEC_RANDISN
++bool 'Randomized IP IDs' CONFIG_GRKERNSEC_RANDID
++bool 'Randomized TCP source ports' CONFIG_GRKERNSEC_RANDSRC
++bool 'Randomized RPC XIDs' CONFIG_GRKERNSEC_RANDRPC
++bool 'Socket restrictions' CONFIG_GRKERNSEC_SOCKET
++if [ "$CONFIG_GRKERNSEC_SOCKET" != "n" ]; then
++bool ' Deny any sockets to group' CONFIG_GRKERNSEC_SOCKET_ALL
++if [ "$CONFIG_GRKERNSEC_SOCKET_ALL" != "n" ]; then
++int ' GID to deny all sockets for:' CONFIG_GRKERNSEC_SOCKET_ALL_GID 1004
++fi
++bool ' Deny client sockets to group' CONFIG_GRKERNSEC_SOCKET_CLIENT
++if [ "$CONFIG_GRKERNSEC_SOCKET_CLIENT" != "n" ]; then
++int ' GID to deny client sockets for:' CONFIG_GRKERNSEC_SOCKET_CLIENT_GID 1003
++fi
++bool ' Deny server sockets to group' CONFIG_GRKERNSEC_SOCKET_SERVER
++if [ "$CONFIG_GRKERNSEC_SOCKET_SERVER" != "n" ]; then
++int ' GID to deny server sockets for:' CONFIG_GRKERNSEC_SOCKET_SERVER_GID 1002
++fi
++fi
++endmenu
++if [ "$CONFIG_SYSCTL" != "n" ]; then
++mainmenu_option next_comment
++comment 'Sysctl support'
++bool 'Sysctl support' CONFIG_GRKERNSEC_SYSCTL
++endmenu
++fi
++mainmenu_option next_comment
++comment 'Logging options'
++int 'Seconds in between log messages (minimum)' CONFIG_GRKERNSEC_FLOODTIME 10
++int 'Number of messages in a burst (maximum)' CONFIG_GRKERNSEC_FLOODBURST 4
++endmenu
++fi
+diff -urN linux-2.4.21/grsecurity/Makefile linux-2.4.21/grsecurity/Makefile
+--- linux-2.4.21/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/Makefile 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,24 @@
++# grsecurity's ACL system was originally written in 2001 by Michael Dalton
++# during 2001, 2002, and 2003 it has been completely redesigned by
++# Brad Spengler
++#
++# All code in this directory and various hooks inserted throughout the kernel
++# are copyright Brad Spengler, and released under the GPL, unless otherwise
++# noted (as in obsd_rand.c)
++
++O_TARGET := grsec.o
++
++obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
++ grsec_mount.o grsec_rand.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
++ grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o
++
++ifeq ($(CONFIG_GRKERNSEC),y)
++obj-y += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o obsd_rand.o \
++ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \
++ gracl_learn.o
++obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o
++else
++obj-y += grsec_disabled.o
++endif
++
++include $(TOPDIR)/Rules.make
+diff -urN linux-2.4.21/grsecurity/gracl.c linux-2.4.21/grsecurity/gracl.c
+--- linux-2.4.21/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl.c 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,2653 @@
++/*
++ * grsecurity/gracl.c
++ * Copyright Brad Spengler 2001, 2002, 2003
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/proc_fs.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/types.h>
++#include <linux/capability.h>
++#include <linux/sysctl.h>
++#include <linux/gracl.h>
++#include <linux/gralloc.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++#include <asm/uaccess.h>
++#include <asm/errno.h>
++#include <asm/mman.h>
++
++static struct acl_role_db acl_role_set;
++static struct acl_role_label *role_list_head;
++static struct name_db name_set;
++static struct name_db inodev_set;
++
++static struct acl_role_label *default_role;
++
++static u16 acl_sp_role_value;
++
++static DECLARE_MUTEX(gr_dev_sem);
++rwlock_t gr_inode_lock = RW_LOCK_UNLOCKED;
++
++extern char *gr_shared_page[2][NR_CPUS];
++
++static unsigned long gr_status = GR_STATUS_INIT;
++
++extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum);
++extern void gr_clear_learn_entries(void);
++
++#ifdef CONFIG_GRKERNSEC_RESLOG
++extern __inline__ void gr_log_resource(const struct task_struct *task,
++ const int res,
++ const unsigned long wanted);
++#endif
++
++static unsigned char system_salt[GR_SALT_LEN];
++static unsigned char system_sum[GR_SHA_LEN];
++
++static struct sprole_pw **acl_special_roles = NULL;
++static __u16 num_sprole_pws = 0;
++
++static struct acl_role_label *kernel_role = NULL;
++
++/* The following are used to keep a place held in the hash table when we move
++ entries around. They can be replaced during insert. */
++
++static struct acl_subject_label *deleted_subject;
++static struct acl_object_label *deleted_object;
++static struct name_entry *deleted_inodev;
++
++/* for keeping track of the last and final allocated subjects, since
++ nested subject parsing is tricky
++*/
++static struct acl_subject_label *s_last = NULL;
++static struct acl_subject_label *s_final = NULL;
++
++static unsigned int gr_auth_attempts = 0;
++static unsigned long gr_auth_expires = 0UL;
++
++extern int gr_init_uidset(void);
++extern void gr_free_uidset(void);
++extern void gr_remove_uid(uid_t uid);
++extern int gr_find_uid(uid_t uid);
++
++__inline__ int
++gr_acl_is_enabled(void)
++{
++ return (gr_status & GR_READY);
++}
++
++static __inline__ int
++gr_streq(const char *a, const char *b, const __u16 lena, const __u16 lenb)
++{
++ int i;
++ unsigned long *l1;
++ unsigned long *l2;
++ unsigned char *c1;
++ unsigned char *c2;
++ int num_longs;
++
++ if (likely(lena != lenb))
++ return 0;
++
++ l1 = (unsigned long *)a;
++ l2 = (unsigned long *)b;
++
++ num_longs = lena / sizeof(unsigned long);
++
++ for (i = num_longs; i--; l1++, l2++) {
++ if (unlikely(*l1 != *l2))
++ return 0;
++ }
++
++ c1 = (unsigned char *) l1;
++ c2 = (unsigned char *) l2;
++
++ i = lena - (num_longs * sizeof(unsigned long));
++
++ for (; i--; c1++, c2++) {
++ if (unlikely(*c1 != *c2))
++ return 0;
++ }
++
++ return 1;
++}
++
++static __inline__ char *
++d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
++ char *buf, int buflen)
++{
++ char *res;
++ struct dentry *our_dentry;
++ struct vfsmount *our_mount;
++ struct vfsmount *rootmnt;
++ struct dentry *root;
++
++ our_dentry = (struct dentry *) dentry;
++ our_mount = (struct vfsmount *) vfsmnt;
++
++ read_lock(&child_reaper->fs->lock);
++ rootmnt = mntget(child_reaper->fs->rootmnt);
++ root = dget(child_reaper->fs->root);
++ read_unlock(&child_reaper->fs->lock);
++
++ spin_lock(&dcache_lock);
++ res = __d_path(our_dentry, our_mount, root, rootmnt, buf, buflen);
++ spin_unlock(&dcache_lock);
++ dput(root);
++ mntput(rootmnt);
++ return res;
++}
++
++char *
++gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return d_real_path(dentry, mnt, gr_shared_page[0][smp_processor_id()],
++ PAGE_SIZE);
++}
++
++char *
++gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return d_real_path(dentry, mnt, gr_shared_page[1][smp_processor_id()],
++ PAGE_SIZE);
++}
++
++__inline__ __u32
++to_gr_audit(const __u32 reqmode)
++{
++ __u32 retmode = 0;
++
++ retmode |= (reqmode & GR_READ) ? GR_AUDIT_READ : 0;
++ retmode |= (reqmode & GR_WRITE) ? GR_AUDIT_WRITE | GR_AUDIT_APPEND : 0;
++ retmode |= (reqmode & GR_APPEND) ? GR_AUDIT_APPEND : 0;
++ retmode |= (reqmode & GR_EXEC) ? GR_AUDIT_EXEC : 0;
++ retmode |= (reqmode & GR_INHERIT) ? GR_AUDIT_INHERIT : 0;
++ retmode |= (reqmode & GR_FIND) ? GR_AUDIT_FIND : 0;
++ retmode |= (reqmode & GR_SETID) ? GR_AUDIT_SETID : 0;
++ retmode |= (reqmode & GR_CREATE) ? GR_AUDIT_CREATE : 0;
++ retmode |= (reqmode & GR_DELETE) ? GR_AUDIT_DELETE : 0;
++
++ return retmode;
++}
++
++__inline__ struct acl_role_label *
++lookup_acl_role_label(const struct task_struct *task, const uid_t uid,
++ const gid_t gid)
++{
++ unsigned long index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size);
++ struct acl_role_label *match;
++ struct role_allowed_ip *ipp;
++ __u8 i = 0;
++
++ match = acl_role_set.r_hash[index];
++
++ while (match
++ && (match->uidgid != uid || !(match->roletype & GR_ROLE_USER))) {
++ index = (index + (1 << i)) % acl_role_set.r_size;
++ match = acl_role_set.r_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (!match || match->uidgid != uid || !(match->roletype & GR_ROLE_USER)) {
++ try_group:
++ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size);
++ match = acl_role_set.r_hash[index];
++ i = 0;
++
++ while (match
++ && (match->uidgid != gid
++ || !(match->roletype & GR_ROLE_GROUP))) {
++ index = (index + (1 << i)) % acl_role_set.r_size;
++ match = acl_role_set.r_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (!match || match->uidgid != gid
++ || !(match->roletype & GR_ROLE_GROUP))
++ match = default_role;
++ else if (likely(!match->allowed_ips)) {
++ return match;
++ } else {
++ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
++ if (likely
++ ((task->curr_ip & ipp->netmask) ==
++ (ipp->addr & ipp->netmask)))
++ return match;
++ }
++ match = default_role;
++ }
++ } else if (likely(!match->allowed_ips)) {
++ return match;
++ } else {
++ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
++ if (likely
++ ((task->curr_ip & ipp->netmask) ==
++ (ipp->addr & ipp->netmask)))
++ return match;
++ }
++ goto try_group;
++ }
++
++ return match;
++}
++
++__inline__ struct acl_subject_label *
++lookup_acl_subj_label(const ino_t ino, const kdev_t dev,
++ const struct acl_role_label *role)
++{
++ unsigned long subj_size = role->subj_hash_size;
++ struct acl_subject_label **s_hash = role->subj_hash;
++ unsigned long index = fhash(ino, dev, subj_size);
++ struct acl_subject_label *match;
++ __u8 i = 0;
++
++ match = s_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ (match->mode & GR_DELETED))) {
++ index = (index + (1 << i)) % subj_size;
++ match = s_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (unlikely(match && (match != deleted_subject) &&
++ (match->inode == ino) && (match->device == dev) &&
++ !(match->mode & GR_DELETED)))
++ return match;
++ else
++ return NULL;
++}
++
++static __inline__ struct acl_object_label *
++lookup_acl_obj_label(const ino_t ino, const kdev_t dev,
++ const struct acl_subject_label *subj)
++{
++ unsigned long obj_size = subj->obj_hash_size;
++ struct acl_object_label **o_hash = subj->obj_hash;
++ unsigned long index = fhash(ino, dev, obj_size);
++ struct acl_object_label *match;
++ __u8 i = 0;
++
++ match = o_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ (match->mode & GR_DELETED))) {
++ index = (index + (1 << i)) % obj_size;
++ match = o_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (unlikely(match && (match != deleted_object) &&
++ (match->inode == ino) && (match->device == dev) &&
++ !(match->mode & GR_DELETED)))
++ return match;
++ else
++ return NULL;
++}
++
++static __inline__ struct acl_object_label *
++lookup_acl_obj_label_create(const ino_t ino, const kdev_t dev,
++ const struct acl_subject_label *subj)
++{
++ unsigned long obj_size = subj->obj_hash_size;
++ struct acl_object_label **o_hash = subj->obj_hash;
++ unsigned long index = fhash(ino, dev, obj_size);
++ struct acl_object_label *match;
++ __u8 i = 0;
++
++ match = o_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ !(match->mode & GR_DELETED))) {
++ index = (index + (1 << i)) % obj_size;
++ match = o_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (unlikely(match && (match != deleted_object) &&
++ (match->inode == ino) && (match->device == dev) &&
++ (match->mode & GR_DELETED)))
++ return match;
++
++ i = 0;
++ index = fhash(ino, dev, obj_size);
++ match = o_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev ||
++ (match->mode & GR_DELETED))) {
++ index = (index + (1 << i)) % obj_size;
++ match = o_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (unlikely(match && (match != deleted_object) &&
++ (match->inode == ino) && (match->device == dev) &&
++ !(match->mode & GR_DELETED)))
++ return match;
++ else
++ return NULL;
++}
++
++static __inline__ struct name_entry *
++lookup_name_entry(const char *name)
++{
++ __u16 len = strlen(name);
++ unsigned long index = nhash(name, len, name_set.n_size);
++ struct name_entry *match;
++ __u8 i = 0;
++
++ match = name_set.n_hash[index];
++
++ while (match && !gr_streq(match->name, name, match->len, len)) {
++ index = (index + (1 << i)) % name_set.n_size;
++ match = name_set.n_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (unlikely(!match || !gr_streq(match->name, name, match->len, len)))
++ return NULL;
++ else
++ return match;
++}
++
++static __inline__ struct name_entry *
++lookup_inodev_entry(const ino_t ino, const kdev_t dev)
++{
++ unsigned long index = fhash(ino, dev, inodev_set.n_size);
++ struct name_entry *match;
++ __u8 i = 0;
++
++ match = inodev_set.n_hash[index];
++
++ while (match && (match->inode != ino || match->device != dev)) {
++ index = (index + (1 << i)) % inodev_set.n_size;
++ match = inodev_set.n_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (unlikely(match && (match != deleted_inodev) &&
++ (match->inode == ino) && (match->device == dev)))
++ return match;
++ else
++ return NULL;
++}
++
++static void
++insert_inodev_entry(struct name_entry *nentry)
++{
++ unsigned long index = fhash(nentry->inode, nentry->device,
++ inodev_set.n_size);
++ struct name_entry **curr;
++ __u8 i = 0;
++
++ curr = &inodev_set.n_hash[index];
++
++ while (*curr && *curr != deleted_inodev) {
++ index = (index + (1 << i)) % inodev_set.n_size;
++ curr = &inodev_set.n_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ *curr = nentry;
++
++ return;
++}
++
++static void
++insert_acl_role_label(struct acl_role_label *role)
++{
++ unsigned long index =
++ rhash(role->uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size);
++ struct acl_role_label **curr;
++ __u8 i = 0;
++
++ curr = &acl_role_set.r_hash[index];
++
++ while (*curr) {
++ index = (index + (1 << i)) % acl_role_set.r_size;
++ curr = &acl_role_set.r_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ *curr = role;
++
++ return;
++}
++
++static int
++insert_name_entry(char *name, const ino_t inode, const kdev_t device)
++{
++ struct name_entry **curr;
++ __u8 i = 0;
++ __u16 len = strlen(name);
++ unsigned long index = nhash(name, len, name_set.n_size);
++
++ curr = &name_set.n_hash[index];
++
++ while (*curr && !gr_streq((*curr)->name, name, (*curr)->len, len)) {
++ index = (index + (1 << i)) % name_set.n_size;
++ curr = &name_set.n_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (!(*curr)) {
++ struct name_entry *nentry =
++ acl_alloc(sizeof (struct name_entry));
++ if (!nentry)
++ return 0;
++ nentry->name = name;
++ nentry->inode = inode;
++ nentry->device = device;
++ nentry->len = len;
++ *curr = nentry;
++ /* insert us into the table searchable by inode/dev */
++ insert_inodev_entry(nentry);
++ }
++
++ return 1;
++}
++
++static void
++insert_acl_obj_label(struct acl_object_label *obj,
++ struct acl_subject_label *subj)
++{
++ unsigned long index =
++ fhash(obj->inode, obj->device, subj->obj_hash_size);
++ struct acl_object_label **curr;
++ __u8 i = 0;
++
++ curr = &subj->obj_hash[index];
++
++ while (*curr && *curr != deleted_object) {
++ index = (index + (1 << i)) % subj->obj_hash_size;
++ curr = &subj->obj_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ *curr = obj;
++
++ return;
++}
++
++static void
++insert_acl_subj_label(struct acl_subject_label *obj,
++ struct acl_role_label *role)
++{
++ unsigned long subj_size = role->subj_hash_size;
++ struct acl_subject_label **s_hash = role->subj_hash;
++ unsigned long index = fhash(obj->inode, obj->device, subj_size);
++ struct acl_subject_label **curr;
++ __u8 i = 0;
++
++ curr = &s_hash[index];
++
++ while (*curr && *curr != deleted_subject) {
++ index = (index + (1 << i)) % subj_size;
++ curr = &s_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ *curr = obj;
++
++ return;
++}
++
++static void **
++create_table(__u32 * len)
++{
++ unsigned long table_sizes[] = {
++ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
++ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
++ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
++ 268435399, 536870909, 1073741789, 2147483647
++ };
++ void *newtable = NULL;
++ unsigned int pwr = 0;
++
++ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) &&
++ table_sizes[pwr] <= (2 * (*len)))
++ pwr++;
++
++ if (table_sizes[pwr] <= (2 * (*len)))
++ return newtable;
++
++ if ((table_sizes[pwr] * sizeof (void *)) <= PAGE_SIZE)
++ newtable =
++ kmalloc(table_sizes[pwr] * sizeof (void *), GFP_KERNEL);
++ else
++ newtable = vmalloc(table_sizes[pwr] * sizeof (void *));
++
++ *len = table_sizes[pwr];
++
++ return newtable;
++}
++
++static int
++init_variables(const unsigned long acl_obj_size,
++ const unsigned long acl_subj_size,
++ const unsigned long acl_ip_size,
++ const unsigned long acl_role_size,
++ const unsigned long allowed_ip_size,
++ const unsigned long acl_trans_size,
++ const __u16 num_sprole_pws)
++{
++ unsigned long stacksize;
++
++ acl_role_set.r_size = acl_role_size;
++ name_set.n_size = (acl_obj_size + acl_subj_size);
++ inodev_set.n_size = (acl_obj_size + acl_subj_size);
++
++ if (!gr_init_uidset())
++ return 1;
++
++ /* set up the stack that holds allocation info */
++
++ stacksize = (3 * acl_obj_size) + (2 * acl_role_size) +
++ (4 * acl_subj_size) + acl_ip_size + (2 * acl_trans_size) +
++ allowed_ip_size + (2 * num_sprole_pws) + 5;
++
++ if (!acl_alloc_stack_init(stacksize))
++ return 1;
++
++ /* create our empty, fake deleted acls */
++ deleted_subject =
++ (struct acl_subject_label *)
++ acl_alloc(sizeof (struct acl_subject_label));
++ deleted_object =
++ (struct acl_object_label *)
++ acl_alloc(sizeof (struct acl_object_label));
++ deleted_inodev =
++ (struct name_entry *) acl_alloc(sizeof (struct name_entry));
++
++ if (!deleted_subject || !deleted_object || !deleted_inodev)
++ return 1;
++
++ memset(deleted_subject, 0, sizeof (struct acl_subject_label));
++ memset(deleted_object, 0, sizeof (struct acl_object_label));
++ memset(deleted_inodev, 0, sizeof (struct name_entry));
++
++ /* We only want 50% full tables for now */
++
++ acl_role_set.r_hash =
++ (struct acl_role_label **) create_table(&acl_role_set.r_size);
++ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size);
++ inodev_set.n_hash =
++ (struct name_entry **) create_table(&inodev_set.n_size);
++
++ if (!acl_role_set.r_hash || !name_set.n_hash || !inodev_set.n_hash)
++ return 1;
++ memset(acl_role_set.r_hash, 0,
++ sizeof (struct acl_role_label *) * acl_role_set.r_size);
++ memset(name_set.n_hash, 0,
++ sizeof (struct name_entry *) * name_set.n_size);
++ memset(inodev_set.n_hash, 0,
++ sizeof (struct name_entry *) * inodev_set.n_size);
++
++ return 0;
++}
++
++static void
++free_variables(void)
++{
++ struct acl_subject_label *s;
++ struct acl_role_label *r;
++ struct task_struct *task;
++
++ gr_clear_learn_entries();
++
++ read_lock(&tasklist_lock);
++ for_each_task(task) {
++ task->acl_sp_role = 0;
++ task->acl_role_id = 0;
++ task->acl = NULL;
++ task->role = NULL;
++ }
++ read_unlock(&tasklist_lock);
++
++ /* free all object hash tables */
++
++ if (role_list_head) {
++ for (r = role_list_head; r; r = r->next) {
++ if (!r->subj_hash)
++ break;
++ for (s = r->proc_subject; s; s = s->next) {
++ if (!s->obj_hash)
++ break;
++ if ((s->obj_hash_size *
++ sizeof (struct acl_object_label *)) <=
++ PAGE_SIZE)
++ kfree(s->obj_hash);
++ else
++ vfree(s->obj_hash);
++ }
++ if ((r->subj_hash_size *
++ sizeof (struct acl_subject_label *)) <= PAGE_SIZE)
++ kfree(r->subj_hash);
++ else
++ vfree(r->subj_hash);
++ }
++ }
++
++ acl_free_all();
++
++ if (acl_role_set.r_hash) {
++ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <=
++ PAGE_SIZE)
++ kfree(acl_role_set.r_hash);
++ else
++ vfree(acl_role_set.r_hash);
++ }
++ if (name_set.n_hash) {
++ if ((name_set.n_size * sizeof (struct name_entry *)) <=
++ PAGE_SIZE)
++ kfree(name_set.n_hash);
++ else
++ vfree(name_set.n_hash);
++ }
++
++ if (inodev_set.n_hash) {
++ if ((inodev_set.n_size * sizeof (struct name_entry *)) <=
++ PAGE_SIZE)
++ kfree(inodev_set.n_hash);
++ else
++ vfree(inodev_set.n_hash);
++ }
++
++ gr_free_uidset();
++
++ memset(&name_set, 0, sizeof (struct name_db));
++ memset(&inodev_set, 0, sizeof (struct name_db));
++ memset(&acl_role_set, 0, sizeof (struct acl_role_db));
++
++ role_list_head = NULL;
++ default_role = NULL;
++
++ return;
++}
++
++static __u32
++count_user_objs(struct acl_object_label *userp)
++{
++ struct acl_object_label o_tmp;
++ __u32 num = 0;
++
++ while (userp) {
++ if (copy_from_user(&o_tmp, userp,
++ sizeof (struct acl_object_label)))
++ break;
++
++ userp = o_tmp.prev;
++ num++;
++ }
++
++ return num;
++}
++
++static struct acl_subject_label *
++do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role);
++
++static int
++copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj,
++ struct acl_role_label *role)
++{
++ struct acl_object_label *o_tmp;
++ unsigned int len;
++ char *tmp;
++
++ while (userp) {
++ if ((o_tmp = (struct acl_object_label *)
++ acl_alloc(sizeof (struct acl_object_label))) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(o_tmp, userp,
++ sizeof (struct acl_object_label)))
++ return -EFAULT;
++
++ userp = o_tmp->prev;
++
++ len = strnlen_user(o_tmp->filename, PATH_MAX);
++
++ if (!len || len >= PATH_MAX)
++ return -EINVAL;
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(tmp, o_tmp->filename, len))
++ return -EFAULT;
++
++ o_tmp->filename = tmp;
++
++ insert_acl_obj_label(o_tmp, subj);
++ if (!insert_name_entry(o_tmp->filename, o_tmp->inode,
++ o_tmp->device))
++ return -ENOMEM;
++
++ if (o_tmp->nested) {
++ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role);
++ if (IS_ERR(o_tmp->nested))
++ return PTR_ERR(o_tmp->nested);
++
++ s_final = o_tmp->nested;
++ }
++ }
++
++ return 0;
++}
++
++static __u32
++count_user_subjs(struct acl_subject_label *userp)
++{
++ struct acl_subject_label s_tmp;
++ __u32 num = 0;
++
++ while (userp) {
++ if (copy_from_user(&s_tmp, userp,
++ sizeof (struct acl_subject_label)))
++ break;
++
++ userp = s_tmp.prev;
++ /* do not count nested subjects against this count, since
++ they are not included in the hash table, but are
++ attached to objects. We have already counted
++ the subjects in userspace for the allocation
++ stack
++ */
++ if (!s_tmp.parent_subject)
++ num++;
++ }
++
++ return num;
++}
++
++static int
++copy_user_allowedips(struct acl_role_label *rolep)
++{
++ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast;
++
++ ruserip = rolep->allowed_ips;
++
++ while (ruserip) {
++ rlast = rtmp;
++
++ if ((rtmp = (struct role_allowed_ip *)
++ acl_alloc(sizeof (struct role_allowed_ip))) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(rtmp, ruserip,
++ sizeof (struct role_allowed_ip)))
++ return -EFAULT;
++
++ ruserip = rtmp->prev;
++
++ if (!rlast) {
++ rtmp->prev = NULL;
++ rolep->allowed_ips = rtmp;
++ } else {
++ rlast->next = rtmp;
++ rtmp->prev = rlast;
++ }
++
++ if (!ruserip)
++ rtmp->next = NULL;
++ }
++
++ return 0;
++}
++
++static int
++copy_user_transitions(struct acl_role_label *rolep)
++{
++ struct role_transition *rusertp, *rtmp = NULL, *rlast;
++ unsigned int len;
++ char *tmp;
++
++ rusertp = rolep->transitions;
++
++ while (rusertp) {
++ rlast = rtmp;
++
++ if ((rtmp = (struct role_transition *)
++ acl_alloc(sizeof (struct role_transition))) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(rtmp, rusertp,
++ sizeof (struct role_transition)))
++ return -EFAULT;
++
++ rusertp = rtmp->prev;
++
++ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN);
++
++ if (!len || len >= GR_SPROLE_LEN)
++ return -EINVAL;
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return -ENOMEM;
++
++ if (copy_from_user(tmp, rtmp->rolename, len))
++ return -EFAULT;
++
++ rtmp->rolename = tmp;
++
++ if (!rlast) {
++ rtmp->prev = NULL;
++ rolep->transitions = rtmp;
++ } else {
++ rlast->next = rtmp;
++ rtmp->prev = rlast;
++ }
++
++ if (!rusertp)
++ rtmp->next = NULL;
++ }
++
++ return 0;
++}
++
++static struct acl_subject_label *
++do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role)
++{
++ struct acl_subject_label *s_tmp = NULL;
++ unsigned int len;
++ char *tmp;
++ __u32 num_objs;
++ struct acl_ip_label **i_tmp, *i_utmp2;
++ unsigned long i_num;
++ int err;
++
++
++ if ((s_tmp = (struct acl_subject_label *)
++ acl_alloc(sizeof (struct acl_subject_label))) == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ if (copy_from_user(s_tmp, userp,
++ sizeof (struct acl_subject_label)))
++ return ERR_PTR(-EFAULT);
++
++ if (!s_last) {
++ s_tmp->prev = NULL;
++ role->proc_subject = s_tmp;
++ } else {
++ s_last->next = s_tmp;
++ s_tmp->prev = s_last;
++ }
++
++ s_last = s_tmp;
++
++ len = strnlen_user(s_tmp->filename, PATH_MAX);
++
++ if (!len || len >= PATH_MAX)
++ return ERR_PTR(-EINVAL);
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ if (copy_from_user(tmp, s_tmp->filename, len))
++ return ERR_PTR(-EFAULT);
++
++ s_tmp->filename = tmp;
++
++ if (!strcmp(s_tmp->filename, "/"))
++ role->root_label = s_tmp;
++
++ /* set up object hash table */
++ num_objs = count_user_objs(s_tmp->proc_object);
++
++ s_tmp->obj_hash_size = num_objs;
++ s_tmp->obj_hash =
++ (struct acl_object_label **)
++ create_table(&(s_tmp->obj_hash_size));
++
++ if (!s_tmp->obj_hash)
++ return ERR_PTR(-ENOMEM);
++
++ memset(s_tmp->obj_hash, 0,
++ s_tmp->obj_hash_size *
++ sizeof (struct acl_object_label *));
++
++ /* copy before adding in objects, since a nested
++ acl could be found and be the final subject
++ copied
++ */
++
++ s_final = s_tmp;
++
++ /* add in objects */
++ err = copy_user_objs(s_tmp->proc_object, s_tmp, role);
++
++ if (err)
++ return ERR_PTR(err);
++
++ /* add in ip acls */
++
++ if (!s_tmp->ip_num) {
++ s_tmp->ips = NULL;
++ goto insert;
++ }
++
++ i_tmp =
++ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num *
++ sizeof (struct
++ acl_ip_label *));
++
++ if (!i_tmp)
++ return ERR_PTR(-ENOMEM);
++
++ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) {
++ *(i_tmp + i_num) =
++ (struct acl_ip_label *)
++ acl_alloc(sizeof (struct acl_ip_label));
++ if (!*(i_tmp + i_num))
++ return ERR_PTR(-ENOMEM);
++
++ if (copy_from_user
++ (&i_utmp2, s_tmp->ips + i_num,
++ sizeof (struct acl_ip_label *)))
++ return ERR_PTR(-EFAULT);
++
++ if (copy_from_user
++ (*(i_tmp + i_num), i_utmp2,
++ sizeof (struct acl_ip_label)))
++ return ERR_PTR(-EFAULT);
++ }
++
++ s_tmp->ips = i_tmp;
++
++insert:
++ if (!insert_name_entry(s_tmp->filename, s_tmp->inode,
++ s_tmp->device))
++ return ERR_PTR(-ENOMEM);
++
++ return s_tmp;
++}
++
++static int
++copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role)
++{
++ struct acl_subject_label s_pre;
++ struct acl_subject_label * ret;
++ int err;
++
++ while (userp) {
++ if (copy_from_user(&s_pre, userp,
++ sizeof (struct acl_subject_label)))
++ return -EFAULT;
++
++ /* do not add nested subjects here, add
++ while parsing objects
++ */
++
++ if (s_pre.parent_subject) {
++ userp = s_pre.prev;
++ continue;
++ }
++
++ ret = do_copy_user_subj(userp, role);
++
++ err = PTR_ERR(ret);
++ if (IS_ERR(ret))
++ return err;
++
++ insert_acl_subj_label(ret, role);
++
++ userp = s_pre.prev;
++ }
++
++ s_final->next = NULL;
++
++ return 0;
++}
++
++static int
++copy_user_acl(struct gr_arg *arg)
++{
++ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2, *r_last;
++ struct sprole_pw *sptmp;
++ unsigned long r_num;
++ unsigned int len;
++ char *tmp;
++ int err = 0;
++ __u16 i;
++ __u32 num_subjs;
++
++ /* we need a default and kernel role */
++ if (arg->role_db.r_entries < 2)
++ return -EINVAL;
++
++ /* copy special role authentication info from userspace */
++
++ num_sprole_pws = arg->num_sprole_pws;
++ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *));
++
++ if (!acl_special_roles) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ for (i = 0; i < num_sprole_pws; i++) {
++ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw));
++ if (!sptmp) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++ if (copy_from_user(sptmp, arg->sprole_pws + i,
++ sizeof (struct sprole_pw))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ len =
++ strnlen_user(sptmp->rolename, GR_SPROLE_LEN);
++
++ if (!len || len >= GR_SPROLE_LEN) {
++ err = -EINVAL;
++ goto cleanup;
++ }
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ if (copy_from_user(tmp, sptmp->rolename, len)) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
++ printk(KERN_ALERT "Copying special role %s\n", tmp);
++#endif
++ sptmp->rolename = tmp;
++ acl_special_roles[i] = sptmp;
++ }
++
++ r_utmp = (struct acl_role_label **) arg->role_db.r_table;
++
++ for (r_num = 0; r_num < arg->role_db.r_entries; r_num++) {
++ r_last = r_tmp;
++
++ r_tmp = acl_alloc(sizeof (struct acl_role_label));
++
++ if (!r_tmp) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ if (copy_from_user(&r_utmp2, r_utmp + r_num,
++ sizeof (struct acl_role_label *))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ if (copy_from_user(r_tmp, r_utmp2,
++ sizeof (struct acl_role_label))) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++
++ if (!r_last) {
++ r_tmp->prev = NULL;
++ role_list_head = r_tmp;
++ } else {
++ r_last->next = r_tmp;
++ r_tmp->prev = r_last;
++ }
++
++ if (r_num == (arg->role_db.r_entries - 1))
++ r_tmp->next = NULL;
++
++ len = strnlen_user(r_tmp->rolename, PATH_MAX);
++
++ if (!len || len >= PATH_MAX) {
++ err = -EINVAL;
++ goto cleanup;
++ }
++
++ if ((tmp = (char *) acl_alloc(len)) == NULL) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++ if (copy_from_user(tmp, r_tmp->rolename, len)) {
++ err = -EFAULT;
++ goto cleanup;
++ }
++ r_tmp->rolename = tmp;
++
++ if (!strcmp(r_tmp->rolename, "default")
++ && (r_tmp->roletype & GR_ROLE_DEFAULT)) {
++ default_role = r_tmp;
++ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) {
++ kernel_role = r_tmp;
++ }
++
++ num_subjs = count_user_subjs(r_tmp->proc_subject);
++
++ r_tmp->subj_hash_size = num_subjs;
++ r_tmp->subj_hash =
++ (struct acl_subject_label **)
++ create_table(&(r_tmp->subj_hash_size));
++
++ if (!r_tmp->subj_hash) {
++ err = -ENOMEM;
++ goto cleanup;
++ }
++
++ err = copy_user_allowedips(r_tmp);
++ if (err)
++ goto cleanup;
++
++ err = copy_user_transitions(r_tmp);
++ if (err)
++ goto cleanup;
++
++ memset(r_tmp->subj_hash, 0,
++ r_tmp->subj_hash_size *
++ sizeof (struct acl_subject_label *));
++
++ s_last = NULL;
++
++ err = copy_user_subjs(r_tmp->proc_subject, r_tmp);
++
++ if (err)
++ goto cleanup;
++
++ insert_acl_role_label(r_tmp);
++ }
++
++ goto return_err;
++ cleanup:
++ free_variables();
++ return_err:
++ return err;
++
++}
++
++static int
++gracl_init(struct gr_arg *args)
++{
++ int error = 0;
++
++ memcpy(&system_salt, args->salt, sizeof (system_salt));
++ memcpy(&system_sum, args->sum, sizeof (system_sum));
++
++ if (init_variables(args->role_db.o_entries, args->role_db.s_entries,
++ args->role_db.i_entries, args->role_db.r_entries,
++ args->role_db.a_entries, args->role_db.t_entries,
++ args->num_sprole_pws)) {
++ security_alert_good(GR_INITF_ACL_MSG, GR_VERSION);
++ error = -ENOMEM;
++ free_variables();
++ goto out;
++ }
++
++ error = copy_user_acl(args);
++ if (error)
++ goto out;
++
++ if ((error = gr_set_acls(0))) {
++ free_variables();
++ goto out;
++ }
++
++ gr_status |= GR_READY;
++ out:
++ return error;
++}
++
++static struct acl_object_label *
++chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_subject_label *subj)
++{
++ struct dentry *dentry = (struct dentry *) l_dentry;
++ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
++ struct dentry *root;
++ struct vfsmount *rootmnt;
++ struct acl_object_label *retval;
++
++ read_lock(&child_reaper->fs->lock);
++ rootmnt = mntget(child_reaper->fs->rootmnt);
++ root = dget(child_reaper->fs->root);
++ read_unlock(&child_reaper->fs->lock);
++ spin_lock(&dcache_lock);
++
++ for (;;) {
++ if (unlikely(dentry == root && mnt == rootmnt))
++ break;
++ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) {
++ if (mnt->mnt_parent == mnt)
++ break;
++
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_obj_label(dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, subj);
++ read_unlock(&gr_inode_lock);
++ if (unlikely(retval != NULL))
++ goto out;
++
++ dentry = mnt->mnt_mountpoint;
++ mnt = mnt->mnt_parent;
++ continue;
++ }
++
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_obj_label(dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, subj);
++ read_unlock(&gr_inode_lock);
++ if (unlikely(retval != NULL))
++ goto out;
++
++ dentry = dentry->d_parent;
++ }
++
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_obj_label(dentry->d_inode->i_ino, dentry->d_inode->i_dev,
++ subj);
++ read_unlock(&gr_inode_lock);
++
++ if (unlikely(retval == NULL)) {
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_obj_label(root->d_inode->i_ino,
++ root->d_inode->i_dev, subj);
++ read_unlock(&gr_inode_lock);
++ }
++ out:
++ spin_unlock(&dcache_lock);
++ dput(root);
++ mntput(rootmnt);
++
++ return retval;
++}
++
++static struct acl_subject_label *
++chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
++ const struct acl_role_label *role)
++{
++ struct dentry *dentry = (struct dentry *) l_dentry;
++ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
++ struct dentry *root;
++ struct vfsmount *rootmnt;
++ struct acl_subject_label *retval;
++
++ read_lock(&child_reaper->fs->lock);
++ rootmnt = mntget(child_reaper->fs->rootmnt);
++ root = dget(child_reaper->fs->root);
++ read_unlock(&child_reaper->fs->lock);
++ spin_lock(&dcache_lock);
++
++ for (;;) {
++ if (unlikely(dentry == root && mnt == rootmnt))
++ break;
++ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) {
++ if (mnt->mnt_parent == mnt)
++ break;
++
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_subj_label(dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, role);
++ read_unlock(&gr_inode_lock);
++ if (unlikely(retval != NULL))
++ goto out;
++
++ dentry = mnt->mnt_mountpoint;
++ mnt = mnt->mnt_parent;
++ continue;
++ }
++
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_subj_label(dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, role);
++ read_unlock(&gr_inode_lock);
++ if (unlikely(retval != NULL))
++ goto out;
++
++ dentry = dentry->d_parent;
++ }
++
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_subj_label(dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, role);
++ read_unlock(&gr_inode_lock);
++
++ if (unlikely(retval == NULL)) {
++ read_lock(&gr_inode_lock);
++ retval =
++ lookup_acl_subj_label(root->d_inode->i_ino,
++ root->d_inode->i_dev, role);
++ read_unlock(&gr_inode_lock);
++ }
++ out:
++ spin_unlock(&dcache_lock);
++ dput(root);
++ mntput(rootmnt);
++
++ return retval;
++}
++
++static __inline__ void
++gr_log_learn(const struct acl_role_label *role, const uid_t uid, const gid_t gid,
++ const struct task_struct *task, const char *pathname,
++ const __u32 mode)
++{
++ security_learn(GR_LEARN_AUDIT_MSG, role->rolename, role->roletype,
++ uid, gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
++ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
++ 1, 1, pathname, (unsigned long) mode, NIPQUAD(task->curr_ip));
++
++ return;
++}
++
++__u32
++gr_check_link(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const struct dentry * old_dentry, const struct vfsmount * old_mnt)
++{
++ struct acl_object_label *obj;
++ __u32 oldmode, newmode;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return (GR_WRITE | GR_CREATE);
++
++ obj = chk_obj_label(old_dentry, old_mnt, current->acl);
++ oldmode = obj->mode;
++
++ if (current->acl->mode & GR_LEARN)
++ oldmode |= (GR_WRITE | GR_CREATE);
++ newmode =
++ gr_check_create(new_dentry, parent_dentry, parent_mnt,
++ oldmode | GR_CREATE | GR_AUDIT_CREATE |
++ GR_AUDIT_WRITE | GR_SUPPRESS);
++
++ if ((newmode & oldmode) == oldmode)
++ return newmode;
++ else if (current->acl->mode & GR_LEARN) {
++ gr_log_learn(current->role, current->uid, current->gid,
++ current, gr_to_filename(old_dentry, old_mnt), oldmode);
++ return (GR_WRITE | GR_CREATE);
++ } else if (newmode & GR_SUPPRESS)
++ return GR_SUPPRESS;
++ else
++ return 0;
++}
++
++__u32
++gr_search_file(const struct dentry * dentry, const __u32 mode,
++ const struct vfsmount * mnt)
++{
++ __u32 retval = mode;
++ struct acl_subject_label *curracl;
++ struct acl_object_label *currobj;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return (mode & ~GR_AUDITS);
++
++ curracl = current->acl;
++
++ currobj = chk_obj_label(dentry, mnt, curracl);
++ retval = currobj->mode & mode;
++
++ if (unlikely
++ ((curracl->mode & GR_LEARN) && (mode != GR_PTRACERD)
++ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ retval = new_mode;
++
++ if (!(mode & GR_NOLEARN))
++ gr_log_learn(current->role, current->uid, current->gid,
++ current, gr_to_filename(dentry, mnt), new_mode);
++ }
++
++ return retval;
++}
++
++__u32
++gr_check_create(const struct dentry * new_dentry, const struct dentry * parent,
++ const struct vfsmount * mnt, const __u32 mode)
++{
++ struct name_entry *match;
++ struct acl_object_label *matchpo;
++ struct acl_subject_label *curracl;
++ __u32 retval;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return (mode & ~GR_AUDITS);
++
++ match = lookup_name_entry(gr_to_filename(new_dentry, mnt));
++
++ if (!match)
++ goto check_parent;
++
++ curracl = current->acl;
++
++ read_lock(&gr_inode_lock);
++ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl);
++ read_unlock(&gr_inode_lock);
++
++ if (matchpo) {
++ if ((matchpo->mode & mode) !=
++ (mode & ~(GR_AUDITS | GR_SUPPRESS))
++ && curracl->mode & GR_LEARN) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ gr_log_learn(current->role, current->uid, current->gid,
++ current, gr_to_filename(new_dentry, mnt), new_mode);
++
++ return new_mode;
++ }
++ return (matchpo->mode & mode);
++ }
++
++ check_parent:
++ curracl = current->acl;
++
++ matchpo = chk_obj_label(parent, mnt, curracl);
++ retval = matchpo->mode & mode;
++
++ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS)))
++ && (curracl->mode & GR_LEARN)) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ gr_log_learn(current->role, current->uid, current->gid,
++ current, gr_to_filename(new_dentry, mnt), new_mode);
++ return new_mode;
++ }
++
++ return retval;
++}
++
++int
++gr_check_hidden_task(const struct task_struct *task)
++{
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ if (!(task->acl->mode & GR_FIND) && !(current->acl->mode & GR_VIEW))
++ return 1;
++
++ return 0;
++}
++
++int
++gr_check_protected_task(const struct task_struct *task)
++{
++ if (unlikely(!(gr_status & GR_READY) || !task))
++ return 0;
++
++ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL))
++ return 1;
++
++ return 0;
++}
++
++__inline__ void
++gr_copy_label(struct task_struct *tsk)
++{
++ tsk->used_accept = 0;
++ tsk->used_connect = 0;
++ tsk->acl_sp_role = 0;
++ tsk->acl_role_id = current->acl_role_id;
++ tsk->acl = current->acl;
++ tsk->role = current->role;
++ tsk->curr_ip = current->curr_ip;
++ if (current->exec_file)
++ get_file(current->exec_file);
++ tsk->exec_file = current->exec_file;
++ tsk->is_writable = current->is_writable;
++ if (unlikely(current->used_accept))
++ current->curr_ip = 0;
++
++ return;
++}
++
++static __inline__ void
++gr_set_proc_res(void)
++{
++ struct acl_subject_label *proc;
++ unsigned short i;
++
++ proc = current->acl;
++
++ if (proc->mode & GR_LEARN)
++ return;
++
++ for (i = 0; i < RLIM_NLIMITS; i++) {
++ if (!(proc->resmask & (1 << i)))
++ continue;
++
++ current->rlim[i].rlim_cur = proc->res[i].rlim_cur;
++ current->rlim[i].rlim_max = proc->res[i].rlim_max;
++ }
++
++ return;
++}
++
++static __inline__ void
++do_set_role_label(struct task_struct *task, const uid_t uid, const gid_t gid)
++{
++ task->role = lookup_acl_role_label(task, uid, gid);
++
++ return;
++}
++
++void
++gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid)
++{
++ struct acl_object_label *obj;
++ struct file *filp;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ filp = task->exec_file;
++
++ /* kernel process, we'll give them the kernel role */
++ if (unlikely(!filp)) {
++ task->role = kernel_role;
++ task->acl = kernel_role->root_label;
++ return;
++ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL))
++ do_set_role_label(task, uid, gid);
++
++ task->acl =
++ chk_subj_label(filp->f_dentry, filp->f_vfsmnt, task->role);
++
++ task->is_writable = 0;
++
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
++ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
++#endif
++
++ gr_set_proc_res();
++
++ return;
++}
++
++void
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ struct acl_subject_label *newacl;
++ struct acl_object_label *obj;
++ __u32 retmode;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ newacl = chk_subj_label(dentry, mnt, current->role);
++
++ obj = chk_obj_label(dentry, mnt, current->acl);
++ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT);
++
++ if ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT)) {
++ if (obj->nested)
++ current->acl = obj->nested;
++ else
++ current->acl = newacl;
++ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT)
++ security_audit(GR_INHERIT_ACL_MSG, current->acl->filename,
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++
++ current->is_writable = 0;
++
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(dentry, mnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ current->is_writable = 1;
++ obj = chk_obj_label(dentry, mnt, current->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ current->is_writable = 1;
++
++ gr_set_proc_res();
++
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
++ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", current->comm, current->pid, current->role->rolename, current->acl->filename);
++#endif
++ return;
++}
++
++static __inline__ void
++do_handle_delete(const ino_t ino, const kdev_t dev)
++{
++ struct acl_object_label *matchpo;
++ struct acl_subject_label *matchps;
++ struct acl_subject_label *i;
++ struct acl_role_label *role;
++
++ for (role = role_list_head; role; role = role->next) {
++ for (i = role->proc_subject; i; i = i->next) {
++ if (unlikely(i->parent_subject &&
++ (i->inode == ino) &&
++ (i->device == dev)))
++ i->mode |= GR_DELETED;
++ if (unlikely((matchpo =
++ lookup_acl_obj_label(ino, dev, i)) != NULL))
++ matchpo->mode |= GR_DELETED;
++ }
++
++ if (unlikely((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL))
++ matchps->mode |= GR_DELETED;
++ }
++
++ return;
++}
++
++void
++gr_handle_delete(const ino_t ino, const kdev_t dev)
++{
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ write_lock(&gr_inode_lock);
++ if (unlikely((unsigned long)lookup_inodev_entry(ino, dev)))
++ do_handle_delete(ino, dev);
++ write_unlock(&gr_inode_lock);
++
++ return;
++}
++
++static __inline__ void
++update_acl_obj_label(const ino_t oldinode, const kdev_t olddevice,
++ const ino_t newinode, const kdev_t newdevice,
++ struct acl_subject_label *subj)
++{
++ unsigned long index = fhash(oldinode, olddevice, subj->obj_hash_size);
++ struct acl_object_label **match;
++ struct acl_object_label *tmp;
++ __u8 i = 0;
++
++ match = &subj->obj_hash[index];
++
++ while (*match && ((*match)->inode != oldinode ||
++ (*match)->device != olddevice ||
++ !((*match)->mode & GR_DELETED))) {
++ index = (index + (1 << i)) % subj->obj_hash_size;
++ match = &subj->obj_hash[index];
++ i = (i + 1) % 32;
++ }
++
++ if (*match && ((*match) != deleted_object)
++ && ((*match)->inode == oldinode)
++ && ((*match)->device == olddevice)
++ && ((*match)->mode & GR_DELETED)) {
++ tmp = *match;
++ tmp->inode = newinode;
++ tmp->device = newdevice;
++ tmp->mode &= ~GR_DELETED;
++
++ *match = deleted_object;
++
++ insert_acl_obj_label(tmp, subj);
++ }
++
++ return;
++}
++
++static __inline__ void
++update_acl_subj_label(const ino_t oldinode, const kdev_t olddevice,
++ const ino_t newinode, const kdev_t newdevice,
++ struct acl_role_label *role)
++{
++ struct acl_subject_label **s_hash = role->subj_hash;
++ unsigned long subj_size = role->subj_hash_size;
++ unsigned long index = fhash(oldinode, olddevice, subj_size);
++ struct acl_subject_label **match;
++ struct acl_subject_label *tmp;
++ __u8 i = 0;
++
++ match = &s_hash[index];
++
++ while (*match && ((*match)->inode != oldinode ||
++ (*match)->device != olddevice ||
++ !((*match)->mode & GR_DELETED))) {
++ index = (index + (1 << i)) % subj_size;
++ i = (i + 1) % 32;
++ match = &s_hash[index];
++ }
++
++ if (*match && (*match != deleted_subject)
++ && ((*match)->inode == oldinode)
++ && ((*match)->device == olddevice)
++ && ((*match)->mode & GR_DELETED)) {
++ tmp = *match;
++
++ tmp->inode = newinode;
++ tmp->device = newdevice;
++ tmp->mode &= ~GR_DELETED;
++
++ *match = deleted_subject;
++
++ insert_acl_subj_label(tmp, role);
++ }
++
++ return;
++}
++
++static __inline__ void
++update_inodev_entry(const ino_t oldinode, const kdev_t olddevice,
++ const ino_t newinode, const kdev_t newdevice)
++{
++ unsigned long index = fhash(oldinode, olddevice, inodev_set.n_size);
++ struct name_entry **match;
++ struct name_entry *tmp;
++ __u8 i = 0;
++
++ match = &inodev_set.n_hash[index];
++
++ while (*match
++ && ((*match)->inode != oldinode
++ || (*match)->device != olddevice)) {
++ index = (index + (1 << i)) % inodev_set.n_size;
++ i = (i + 1) % 32;
++ match = &inodev_set.n_hash[index];
++ }
++
++ if (*match && (*match != deleted_inodev)
++ && ((*match)->inode == oldinode)
++ && ((*match)->device == olddevice)) {
++ tmp = *match;
++
++ tmp->inode = newinode;
++ tmp->device = newdevice;
++
++ *match = deleted_inodev;
++
++ insert_inodev_entry(tmp);
++ }
++
++ return;
++}
++
++static __inline__ void
++do_handle_create(const struct name_entry *matchn, const struct dentry *dentry,
++ const struct vfsmount *mnt)
++{
++ struct acl_subject_label *i;
++ struct acl_role_label *role;
++
++ for (role = role_list_head; role; role = role->next) {
++ update_acl_subj_label(matchn->inode, matchn->device,
++ dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, role);
++
++ for (i = role->proc_subject; i; i = i->next) {
++ if (unlikely(i->parent_subject &&
++ (i->inode == dentry->d_inode->i_ino) &&
++ (i->device == dentry->d_inode->i_dev))) {
++ i->inode = dentry->d_inode->i_ino;
++ i->device = dentry->d_inode->i_dev;
++ }
++ update_acl_obj_label(matchn->inode, matchn->device,
++ dentry->d_inode->i_ino,
++ dentry->d_inode->i_dev, i);
++ }
++ }
++
++ update_inodev_entry(matchn->inode, matchn->device,
++ dentry->d_inode->i_ino, dentry->d_inode->i_dev);
++
++ return;
++}
++
++void
++gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ struct name_entry *matchn;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return;
++
++ matchn = lookup_name_entry(gr_to_filename(dentry, mnt));
++
++ if (unlikely((unsigned long)matchn)) {
++ write_lock(&gr_inode_lock);
++ do_handle_create(matchn, dentry, mnt);
++ write_unlock(&gr_inode_lock);
++ }
++
++ return;
++}
++
++int
++gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
++ struct dentry *old_dentry,
++ struct dentry *new_dentry,
++ struct vfsmount *mnt, const __u8 replace)
++{
++ struct name_entry *matchn;
++ int error = 0;
++
++ matchn = lookup_name_entry(gr_to_filename(new_dentry, mnt));
++
++ lock_kernel();
++ error = vfs_rename(old_dir, old_dentry, new_dir, new_dentry);
++ unlock_kernel();
++
++ if (unlikely(error))
++ return error;
++
++ /* we wouldn't have to check d_inode if it weren't for
++ NFS silly-renaming
++ */
++
++ write_lock(&gr_inode_lock);
++ if (unlikely(replace && new_dentry->d_inode)) {
++ if (unlikely(lookup_inodev_entry(new_dentry->d_inode->i_ino,
++ new_dentry->d_inode->i_dev) &&
++ (old_dentry->d_inode->i_nlink <= 1)))
++ do_handle_delete(new_dentry->d_inode->i_ino,
++ new_dentry->d_inode->i_dev);
++ }
++
++ if (unlikely(lookup_inodev_entry(old_dentry->d_inode->i_ino,
++ old_dentry->d_inode->i_dev) &&
++ (old_dentry->d_inode->i_nlink <= 1)))
++ do_handle_delete(old_dentry->d_inode->i_ino,
++ old_dentry->d_inode->i_dev);
++
++ if (unlikely((unsigned long)matchn))
++ do_handle_create(matchn, old_dentry, mnt);
++ write_unlock(&gr_inode_lock);
++
++ return error;
++}
++
++static int
++lookup_special_role_auth(const char *rolename, unsigned char **salt,
++ unsigned char **sum)
++{
++ struct acl_role_label *r;
++ struct role_transition *trans;
++ __u16 i;
++ int found = 0;
++
++ /* check transition table */
++
++ for (trans = current->role->transitions; trans; trans = trans->next) {
++ if (!strcmp(rolename, trans->rolename)) {
++ found = 1;
++ break;
++ }
++ }
++
++ if (!found)
++ return 0;
++
++ /* handle special roles that do not require authentication */
++
++ for (r = role_list_head; r; r = r->next) {
++ if (!strcmp(rolename, r->rolename)
++ && (r->roletype & GR_ROLE_NOPW)) {
++ *salt = NULL;
++ *sum = NULL;
++ return 1;
++ }
++ }
++
++ for (i = 0; i < num_sprole_pws; i++) {
++ if (!strcmp(rolename, acl_special_roles[i]->rolename)) {
++ *salt = acl_special_roles[i]->salt;
++ *sum = acl_special_roles[i]->sum;
++ return 1;
++ }
++ }
++
++ return 0;
++}
++
++static void
++assign_special_role(char *rolename)
++{
++ struct acl_object_label *obj;
++ struct acl_role_label *r;
++ struct acl_role_label *assigned = NULL;
++ struct task_struct *tsk;
++ struct file *filp;
++
++ for (r = role_list_head; r; r = r->next)
++ if (!strcmp(rolename, r->rolename) &&
++ (r->roletype & GR_ROLE_SPECIAL))
++ assigned = r;
++
++ if (!assigned)
++ return;
++
++ tsk = current->p_pptr;
++ filp = tsk->exec_file;
++
++ if (tsk && filp) {
++ tsk->is_writable = 0;
++
++ acl_sp_role_value = (acl_sp_role_value % 65535) + 1;
++ tsk->acl_sp_role = 1;
++ tsk->acl_role_id = acl_sp_role_value;
++ tsk->role = assigned;
++ tsk->acl =
++ chk_subj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role);
++
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ tsk->is_writable = 1;
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ tsk->is_writable = 1;
++
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
++ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid);
++#endif
++ }
++
++ return;
++}
++
++ssize_t
++write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos)
++{
++ struct gr_arg *arg;
++ struct gr_arg usermode;
++ unsigned char *sprole_salt;
++ unsigned char *sprole_sum;
++ int error = sizeof (struct gr_arg);
++ int error2 = 0;
++
++ down(&gr_dev_sem);
++
++ arg = (struct gr_arg *) buf;
++
++ if (count != sizeof (struct gr_arg)) {
++ security_alert_good(GR_DEV_ACL_MSG, count,
++ (int) sizeof (struct gr_arg));
++ error = -EINVAL;
++ goto out;
++ }
++
++ if ((gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES)
++ && time_before_eq(gr_auth_expires, jiffies)) {
++ gr_auth_expires = 0;
++ gr_auth_attempts = 0;
++ }
++
++ if (copy_from_user(&usermode, arg, sizeof (struct gr_arg))) {
++ error = -EFAULT;
++ goto out;
++ }
++
++ if (usermode.mode != SPROLE && time_after(gr_auth_expires, jiffies)) {
++ error = -EBUSY;
++ goto out;
++ }
++
++ /* if non-root trying to do anything other than use a special role,
++ do not attempt authentication, do not count towards authentication
++ locking
++ */
++
++ if (usermode.mode != SPROLE && current->uid) {
++ error = -EPERM;
++ goto out;
++ }
++
++ /* ensure pw and special role name are null terminated */
++
++ usermode.pw[GR_PW_LEN - 1] = '\0';
++ usermode.sp_role[GR_SPROLE_LEN - 1] = '\0';
++
++ /* Okay.
++ * We have our enough of the argument structure..(we have yet
++ * to copy_from_user the tables themselves) . Copy the tables
++ * only if we need them, i.e. for loading operations. */
++
++ switch (usermode.mode) {
++ case STATUS:
++ if (gr_status & GR_READY)
++ error = 1;
++ else
++ error = 2;
++ goto out;
++ case SHUTDOWN:
++ if ((gr_status & GR_READY)
++ && !(chkpw(&usermode, system_salt, system_sum))) {
++ gr_status &= ~GR_READY;
++ security_alert_good(GR_SHUTS_ACL_MSG, DEFAULTSECARGS);
++ free_variables();
++ memset(&usermode, 0, sizeof (struct gr_arg));
++ memset(&system_salt, 0, sizeof (system_salt));
++ memset(&system_sum, 0, sizeof (system_sum));
++ } else if (gr_status & GR_READY) {
++ security_alert(GR_SHUTF_ACL_MSG, DEFAULTSECARGS);
++ error = -EPERM;
++ } else {
++ security_alert_good(GR_SHUTI_ACL_MSG, DEFAULTSECARGS);
++ error = -EAGAIN;
++ }
++ break;
++ case ENABLE:
++ if (!(gr_status & GR_READY) && !(error2 = gracl_init(&usermode)))
++ security_alert_good(GR_ENABLE_ACL_MSG, GR_VERSION);
++ else {
++ if (gr_status & GR_READY)
++ error = -EAGAIN;
++ else
++ error = error2;
++ security_alert(GR_ENABLEF_ACL_MSG, GR_VERSION,
++ DEFAULTSECARGS);
++ }
++ break;
++ case RELOAD:
++ if (!(gr_status & GR_READY)) {
++ security_alert_good(GR_RELOADI_ACL_MSG);
++ error = -EAGAIN;
++ } else if (!(chkpw(&usermode, system_salt, system_sum))) {
++ lock_kernel();
++ gr_status &= ~GR_READY;
++ free_variables();
++ if (!(error2 = gracl_init(&usermode))) {
++ unlock_kernel();
++ security_alert_good(GR_RELOAD_ACL_MSG,
++ GR_VERSION);
++ } else {
++ unlock_kernel();
++ error = error2;
++ security_alert(GR_RELOADF_ACL_MSG, GR_VERSION,
++ DEFAULTSECARGS);
++ }
++ } else {
++ security_alert(GR_RELOADF_ACL_MSG, GR_VERSION,
++ DEFAULTSECARGS);
++ error = -EPERM;
++ }
++ break;
++ case SEGVMOD:
++ if (unlikely(!(gr_status & GR_READY))) {
++ security_alert_good(GR_SEGVMODI_ACL_MSG,
++ DEFAULTSECARGS);
++ error = -EAGAIN;
++ break;
++ }
++
++ if (!(chkpw(&usermode, system_salt, system_sum))) {
++ security_alert_good(GR_SEGVMODS_ACL_MSG,
++ DEFAULTSECARGS);
++ if (usermode.segv_device && usermode.segv_inode) {
++ struct acl_subject_label *segvacl;
++ segvacl =
++ lookup_acl_subj_label(usermode.segv_inode,
++ usermode.segv_device,
++ current->role);
++ if (segvacl) {
++ segvacl->crashes = 0;
++ segvacl->expires = 0;
++ }
++ } else if (gr_find_uid(usermode.segv_uid) >= 0) {
++ gr_remove_uid(usermode.segv_uid);
++ }
++ } else {
++ security_alert(GR_SEGVMODF_ACL_MSG, DEFAULTSECARGS);
++ error = -EPERM;
++ }
++ break;
++ case SPROLE:
++ if (unlikely(!(gr_status & GR_READY))) {
++ security_alert_good(GR_SPROLEI_ACL_MSG, DEFAULTSECARGS);
++ error = -EAGAIN;
++ break;
++ }
++
++ if ((current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES)
++ && time_before_eq(current->role->expires, jiffies)) {
++ current->role->expires = 0;
++ current->role->auth_attempts = 0;
++ }
++
++ if (time_after(current->role->expires, jiffies)) {
++ error = -EBUSY;
++ goto out;
++ }
++
++ if (lookup_special_role_auth
++ (usermode.sp_role, &sprole_salt, &sprole_sum)
++ && ((!sprole_salt && !sprole_sum)
++ || !(chkpw(&usermode, sprole_salt, sprole_sum)))) {
++ assign_special_role(usermode.sp_role);
++ security_alert_good(GR_SPROLES_ACL_MSG,
++ (current->p_pptr) ? current->
++ p_pptr->role->rolename : "",
++ acl_sp_role_value, DEFAULTSECARGS);
++ } else {
++ security_alert(GR_SPROLEF_ACL_MSG, usermode.sp_role,
++ DEFAULTSECARGS);
++ error = -EPERM;
++ current->role->auth_attempts++;
++ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) {
++ current->role->expires =
++ jiffies + CONFIG_GRKERNSEC_ACL_TIMEOUT * HZ;
++ security_alert(GR_MAXROLEPW_ACL_MSG,
++ CONFIG_GRKERNSEC_ACL_MAXTRIES,
++ usermode.sp_role, DEFAULTSECARGS);
++ }
++
++ goto out;
++ }
++ break;
++ default:
++ security_alert(GR_INVMODE_ACL_MSG, usermode.mode,
++ DEFAULTSECARGS);
++ error = -EINVAL;
++ break;
++ }
++
++ if (error != -EPERM)
++ goto out;
++
++ gr_auth_attempts++;
++
++ if (gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) {
++ security_alert(GR_MAXPW_ACL_MSG, CONFIG_GRKERNSEC_ACL_MAXTRIES);
++ gr_auth_expires = jiffies + CONFIG_GRKERNSEC_ACL_TIMEOUT * HZ;
++ }
++
++ out:
++ up(&gr_dev_sem);
++ return error;
++}
++
++int
++gr_set_acls(const int type)
++{
++ struct acl_object_label *obj;
++ struct task_struct *task;
++ struct file *filp;
++ unsigned short i;
++
++ read_lock(&tasklist_lock);
++ for_each_task(task) {
++ /* check to see if we're called from the exit handler,
++ if so, only replace ACLs that have inherited the admin
++ ACL */
++
++ if (type && (task->role != current->role ||
++ task->acl_role_id != current->acl_role_id))
++ continue;
++
++ task->acl_role_id = 0;
++
++ if ((filp = task->exec_file)) {
++ do_set_role_label(task, task->uid, task->gid);
++
++ task->acl =
++ chk_subj_label(filp->f_dentry, filp->f_vfsmnt,
++ task->role);
++ if (task->acl) {
++ struct acl_subject_label *curr;
++ curr = task->acl;
++
++ task->is_writable = 0;
++ /* ignore additional mmap checks for processes that are writable
++ by the default ACL */
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
++ if (unlikely(obj->mode & GR_WRITE))
++ task->is_writable = 1;
++
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
++ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
++#endif
++ if (!(curr->mode & GR_LEARN))
++ for (i = 0; i < RLIM_NLIMITS; i++) {
++ if (!(curr->resmask & (1 << i)))
++ continue;
++
++ task->rlim[i].rlim_cur =
++ curr->res[i].rlim_cur;
++ task->rlim[i].rlim_max =
++ curr->res[i].rlim_max;
++ }
++ } else {
++ read_unlock(&tasklist_lock);
++ security_alert_good(GR_DEFACL_MSG, task->comm,
++ task->pid);
++ return 1;
++ }
++ } else {
++ // it's a kernel process
++ task->role = kernel_role;
++ task->acl = kernel_role->root_label;
++#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN
++ task->acl->mode &= ~GR_FIND;
++#endif
++ }
++ }
++ read_unlock(&tasklist_lock);
++ return 0;
++}
++
++void
++gr_learn_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted)
++{
++ struct acl_subject_label *acl;
++
++ if (unlikely((gr_status & GR_READY) &&
++ task->acl && (task->acl->mode & GR_LEARN)))
++ goto skip_reslog;
++
++#ifdef CONFIG_GRKERNSEC_RESLOG
++ gr_log_resource(task, res, wanted);
++#endif
++ skip_reslog:
++
++ if (unlikely(!(gr_status & GR_READY) || !wanted))
++ return;
++
++ acl = task->acl;
++
++ if (likely(!acl || !(acl->mode & GR_LEARN) ||
++ !(acl->resmask & (1 << (unsigned short) res))))
++ return;
++
++ if (wanted >= acl->res[res].rlim_cur) {
++ unsigned long res_add;
++
++ res_add = wanted;
++ switch (res) {
++ case RLIMIT_CPU:
++ res_add += GR_RLIM_CPU_BUMP;
++ break;
++ case RLIMIT_FSIZE:
++ res_add += GR_RLIM_FSIZE_BUMP;
++ break;
++ case RLIMIT_DATA:
++ res_add += GR_RLIM_DATA_BUMP;
++ break;
++ case RLIMIT_STACK:
++ res_add += GR_RLIM_STACK_BUMP;
++ break;
++ case RLIMIT_CORE:
++ res_add += GR_RLIM_CORE_BUMP;
++ break;
++ case RLIMIT_RSS:
++ res_add += GR_RLIM_RSS_BUMP;
++ break;
++ case RLIMIT_NPROC:
++ res_add += GR_RLIM_NPROC_BUMP;
++ break;
++ case RLIMIT_NOFILE:
++ res_add += GR_RLIM_NOFILE_BUMP;
++ break;
++ case RLIMIT_MEMLOCK:
++ res_add += GR_RLIM_MEMLOCK_BUMP;
++ break;
++ case RLIMIT_AS:
++ res_add += GR_RLIM_AS_BUMP;
++ break;
++ case RLIMIT_LOCKS:
++ res_add += GR_RLIM_LOCKS_BUMP;
++ break;
++ }
++
++ acl->res[res].rlim_cur = res_add;
++
++ if (wanted > acl->res[res].rlim_max)
++ acl->res[res].rlim_max = res_add;
++
++ security_learn(GR_LEARN_AUDIT_MSG, current->role->rolename,
++ current->role->roletype, acl->filename,
++ acl->res[res].rlim_cur, acl->res[res].rlim_max,
++ "", (unsigned long) res);
++ }
++
++ return;
++}
++
++#ifdef CONFIG_SYSCTL
++extern struct proc_dir_entry *proc_sys_root;
++
++__u32
++gr_handle_sysctl(const struct ctl_table *table, const void *oldval,
++ const void *newval)
++{
++ struct proc_dir_entry *tmp;
++ struct nameidata nd;
++ const char *proc_sys = "/proc/sys";
++ char *path = gr_shared_page[0][smp_processor_id()];
++ struct acl_object_label *obj;
++ unsigned short len = 0, pos = 0, depth = 0, i;
++ __u32 err = 0;
++ __u32 mode = 0;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 1;
++
++ if (oldval)
++ mode |= GR_READ;
++ if (newval)
++ mode |= GR_WRITE;
++
++ /* convert the requested sysctl entry into a pathname */
++
++ for (tmp = table->de; tmp != proc_sys_root; tmp = tmp->parent) {
++ len += strlen(tmp->name);
++ len++;
++ depth++;
++ }
++
++ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE)
++ return 0; // deny
++
++ memset(path, 0, PAGE_SIZE);
++
++ memcpy(path, proc_sys, strlen(proc_sys));
++
++ pos += strlen(proc_sys);
++
++ for (; depth > 0; depth--) {
++ path[pos] = '/';
++ pos++;
++ for (i = 1, tmp = table->de; tmp != proc_sys_root;
++ tmp = tmp->parent) {
++ if (depth == i) {
++ memcpy(path + pos, tmp->name,
++ strlen(tmp->name));
++ pos += strlen(tmp->name);
++ }
++ i++;
++ }
++ }
++
++ if (path_init(path, LOOKUP_FOLLOW, &nd))
++ err = path_walk(path, &nd);
++
++ if (err)
++ goto out;
++
++ obj = chk_obj_label(nd.dentry, nd.mnt, current->acl);
++ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS);
++
++ if (unlikely((current->acl->mode & GR_LEARN) && ((err & mode) != mode))) {
++ __u32 new_mode = mode;
++
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
++
++ err = new_mode;
++ gr_log_learn(current->role, current->uid, current->gid,
++ current, path, new_mode);
++ } else if ((err & mode) != mode && !(err & GR_SUPPRESS)) {
++ security_alert(GR_SYSCTL_ACL_MSG, "denied", path,
++ (mode & GR_READ) ? " reading" : "",
++ (mode & GR_WRITE) ? " writing" : "",
++ DEFAULTSECARGS);
++ err = 0;
++ } else if ((err & mode) != mode) {
++ err = 0;
++ } else if (((err & mode) == mode) && (err & GR_AUDITS)) {
++ security_audit(GR_SYSCTL_ACL_MSG, "successful",
++ path, (mode & GR_READ) ? " reading" : "",
++ (mode & GR_WRITE) ? " writing" : "",
++ DEFAULTSECARGS);
++ }
++
++ path_release(&nd);
++
++ out:
++ return err;
++}
++#endif
++
++int
++gr_handle_ptrace(struct task_struct *task, const long request)
++{
++ struct file *filp;
++ __u32 retmode;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ filp = task->exec_file;
++
++ if (unlikely(!filp))
++ return 0;
++
++ retmode = gr_search_file(filp->f_dentry, GR_PTRACERD, filp->f_vfsmnt);
++
++ if (retmode & GR_PTRACERD) {
++ switch (request) {
++ case PTRACE_POKETEXT:
++ case PTRACE_POKEDATA:
++ case PTRACE_POKEUSR:
++#if !defined(CONFIG_PPC32) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA)
++ case PTRACE_SETREGS:
++ case PTRACE_SETFPREGS:
++#endif
++#ifdef CONFIG_X86
++ case PTRACE_SETFPXREGS:
++#endif
++#ifdef CONFIG_ALTIVEC
++ case PTRACE_SETVRREGS:
++#endif
++ return 1;
++ default:
++ return 0;
++ }
++ } else if (!(current->acl->mode & GR_OVERRIDE) &&
++ !(current->role->roletype & GR_ROLE_GOD)
++ && (current->acl != task->acl
++ || (current->acl != current->role->root_label
++ && current->pid != task->pid))) {
++ security_alert(GR_PTRACE_ACL_MSG,
++ gr_to_filename(filp->f_dentry, filp->f_vfsmnt),
++ task->comm, task->pid, DEFAULTSECARGS);
++ return 1;
++ }
++
++ return 0;
++}
++
++int
++gr_handle_ptrace_exec(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ __u32 retmode;
++ struct acl_subject_label *subj;
++
++ if (unlikely(!(gr_status & GR_READY)))
++ return 0;
++
++ if (unlikely
++ ((current->ptrace & PT_PTRACED)
++ && !(current->acl->mode & GR_OVERRIDE)))
++ retmode = gr_search_file(dentry, GR_PTRACERD, mnt);
++ else
++ return 0;
++
++ subj = chk_subj_label(dentry, mnt, current->role);
++
++ if (!(retmode & GR_PTRACERD) &&
++ !(current->role->roletype & GR_ROLE_GOD) &&
++ (current->acl != subj)) {
++ security_alert(GR_PTRACE_EXEC_ACL_MSG,
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++ return 1;
++ }
++
++ return 0;
++}
++
++int
++gr_handle_mmap(const struct file *filp, const unsigned long prot)
++{
++ struct acl_object_label *obj, *obj2;
++
++ if (unlikely(!(gr_status & GR_READY) ||
++ (current->acl->mode & GR_OVERRIDE) || !filp ||
++ !(prot & PROT_EXEC)))
++ return 0;
++
++ if (unlikely(current->is_writable))
++ return 0;
++
++ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
++ obj2 = chk_obj_label(filp->f_dentry, filp->f_vfsmnt,
++ current->role->root_label);
++ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) {
++ security_alert(GR_WRITLIB_ACL_MSG,
++ gr_to_filename(filp->f_dentry, filp->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 1;
++ }
++
++ return 0;
++}
++
++int
++gr_acl_handle_mmap(const struct file *file, const unsigned long prot)
++{
++ __u32 mode;
++
++ if (unlikely(!file || !(prot & PROT_EXEC)))
++ return 1;
++
++ mode =
++ gr_search_file(file->f_dentry,
++ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
++ file->f_vfsmnt);
++
++ if (unlikely(!gr_tpe_allow(file) || (!(mode & GR_EXEC) && !(mode & GR_SUPPRESS)))) {
++ security_alert(GR_MMAP_ACL_MSG, "denied",
++ gr_to_filename(file->f_dentry, file->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely(!gr_tpe_allow(file) || !(mode & GR_EXEC))) {
++ return 0;
++ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
++ security_audit(GR_MMAP_ACL_MSG, "successful",
++ gr_to_filename(file->f_dentry, file->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 1;
++ }
++
++ return 1;
++}
++
++int
++gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
++{
++ __u32 mode;
++
++ if (unlikely(!file || !(prot & PROT_EXEC)))
++ return 1;
++
++ mode =
++ gr_search_file(file->f_dentry,
++ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
++ file->f_vfsmnt);
++
++ if (unlikely(!gr_tpe_allow(file) || (!(mode & GR_EXEC) && !(mode & GR_SUPPRESS)))) {
++ security_alert(GR_MPROTECT_ACL_MSG, "denied",
++ gr_to_filename(file->f_dentry, file->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely(!gr_tpe_allow(file) || !(mode & GR_EXEC))) {
++ return 0;
++ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
++ security_audit(GR_MPROTECT_ACL_MSG, "successful",
++ gr_to_filename(file->f_dentry, file->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 1;
++ }
++
++ return 1;
++}
++
++void
++gr_acl_handle_psacct(struct task_struct *task, const long code)
++{
++ unsigned long runtime;
++ unsigned long cputime;
++ unsigned int wday, cday;
++ __u8 whr, chr;
++ __u8 wmin, cmin;
++ __u8 wsec, csec;
++ char cur_tty[64] = { 0 };
++ char parent_tty[64] = { 0 };
++
++ if (unlikely(!(gr_status & GR_READY) || !task->acl ||
++ !(task->acl->mode & GR_PROCACCT)))
++ return;
++
++ runtime = (jiffies - task->start_time) / HZ;
++ wday = runtime / (3600 * 24);
++ runtime -= wday * (3600 * 24);
++ whr = runtime / 3600;
++ runtime -= whr * 3600;
++ wmin = runtime / 60;
++ runtime -= wmin * 60;
++ wsec = runtime;
++
++ cputime = (task->times.tms_utime + task->times.tms_stime) / HZ;
++ cday = cputime / (3600 * 24);
++ cputime -= cday * (3600 * 24);
++ chr = cputime / 3600;
++ cputime -= chr * 3600;
++ cmin = cputime / 60;
++ cputime -= cmin * 60;
++ csec = cputime;
++
++ security_audit(GR_ACL_PROCACCT_MSG, task->comm,
++ task->pid, NIPQUAD(task->curr_ip), tty_name(task->tty,
++ cur_tty),
++ task->uid, task->euid, task->gid, task->egid, wday, whr,
++ wmin, wsec, cday, chr, cmin, csec,
++ (task->
++ flags & PF_SIGNALED) ? "killed by signal" : "exited",
++ code, task->p_pptr->comm, task->p_pptr->pid,
++ NIPQUAD(task->p_pptr->curr_ip),
++ tty_name(task->p_pptr->tty, parent_tty),
++ task->p_pptr->uid, task->p_pptr->euid, task->p_pptr->gid,
++ task->p_pptr->egid);
++
++ return;
++}
++
++void gr_set_kernel_label(struct task_struct *task)
++{
++ if (gr_status & GR_READY) {
++ task->role = kernel_role;
++ task->acl = kernel_role->root_label;
++ }
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/gracl_alloc.c linux-2.4.21/grsecurity/gracl_alloc.c
+--- linux-2.4.21/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_alloc.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,94 @@
++/* stack-based acl allocation tracking (c) Brad Spengler 2002,2003 */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++
++static unsigned long alloc_stack_next = 1;
++static unsigned long alloc_stack_size = 1;
++static void **alloc_stack;
++
++static __inline__ int
++alloc_pop(void)
++{
++ if ((alloc_stack_next - 1) == 0)
++ return 0;
++
++ if (*(alloc_stack + alloc_stack_next - 2))
++ kfree(*(alloc_stack + alloc_stack_next - 2));
++
++ alloc_stack_next--;
++
++ return 1;
++}
++
++static __inline__ void
++alloc_push(void *buf)
++{
++ if (alloc_stack_next >= alloc_stack_size)
++ BUG();
++
++ *(alloc_stack + alloc_stack_next - 1) = buf;
++
++ alloc_stack_next++;
++
++ return;
++}
++
++void *
++acl_alloc(unsigned long len)
++{
++ void *ret;
++
++ if (len > PAGE_SIZE)
++ BUG();
++
++ ret = kmalloc(len, GFP_KERNEL);
++
++ if (ret)
++ alloc_push(ret);
++
++ return ret;
++}
++
++void
++acl_free_all(void)
++{
++ if (gr_acl_is_enabled() || !alloc_stack)
++ return;
++
++ while (alloc_pop()) ;
++
++ if (alloc_stack) {
++ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE)
++ kfree(alloc_stack);
++ else
++ vfree(alloc_stack);
++ }
++
++ alloc_stack = NULL;
++ alloc_stack_size = 1;
++ alloc_stack_next = 1;
++
++ return;
++}
++
++int
++acl_alloc_stack_init(unsigned long size)
++{
++ if ((size * sizeof (void *)) <= PAGE_SIZE)
++ alloc_stack =
++ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL);
++ else
++ alloc_stack = (void **) vmalloc(size * sizeof (void *));
++
++ alloc_stack_size = size;
++
++ if (!alloc_stack)
++ return 0;
++ else
++ return 1;
++}
+diff -urN linux-2.4.21/grsecurity/gracl_cap.c linux-2.4.21/grsecurity/gracl_cap.c
+--- linux-2.4.21/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_cap.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,71 @@
++/* capability handling routines, (c) Brad Spengler 2002,2003 */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/capability.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++static const char *captab_log[29] = {
++ "CAP_CHOWN",
++ "CAP_DAC_OVERRIDE",
++ "CAP_DAC_READ_SEARCH",
++ "CAP_FOWNER",
++ "CAP_FSETID",
++ "CAP_KILL",
++ "CAP_SETGID",
++ "CAP_SETUID",
++ "CAP_SETPCAP",
++ "CAP_LINUX_IMMUTABLE",
++ "CAP_NET_BIND_SERVICE",
++ "CAP_NET_BROADCAST",
++ "CAP_NET_ADMIN",
++ "CAP_NET_RAW",
++ "CAP_IPC_LOCK",
++ "CAP_IPC_OWNER",
++ "CAP_SYS_MODULE",
++ "CAP_SYS_RAWIO",
++ "CAP_SYS_CHROOT",
++ "CAP_SYS_PTRACE",
++ "CAP_SYS_PACCT",
++ "CAP_SYS_ADMIN",
++ "CAP_SYS_BOOT",
++ "CAP_SYS_NICE",
++ "CAP_SYS_RESOURCE",
++ "CAP_SYS_TIME",
++ "CAP_SYS_TTY_CONFIG",
++ "CAP_MKNOD",
++ "CAP_LEASE"
++};
++
++int
++gr_is_capable(const int cap)
++{
++ struct acl_subject_label *curracl;
++
++ if (!gr_acl_is_enabled())
++ return 1;
++
++ curracl = current->acl;
++
++ if (!cap_raised(curracl->cap_lower, cap))
++ return 1;
++
++ if ((curracl->mode & GR_LEARN)
++ && cap_raised(current->cap_effective, cap)) {
++ security_learn(GR_LEARN_AUDIT_MSG, current->role->rolename,
++ current->role->roletype, current->uid,
++ current->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_dentry,
++ current->exec_file->f_vfsmnt) : curracl->filename,
++ curracl->filename, 0UL,
++ 0UL, "", (unsigned long) cap, NIPQUAD(current->curr_ip));
++ return 1;
++ }
++
++ if ((cap >= 0) && (cap < 29) && cap_raised(current->cap_effective, cap))
++ security_alert(GR_CAP_ACL_MSG, captab_log[cap], DEFAULTSECARGS);
++
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/gracl_fs.c linux-2.4.21/grsecurity/gracl_fs.c
+--- linux-2.4.21/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_fs.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,469 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/gracl.h>
++
++__u32
++gr_acl_handle_hidden_file(const struct dentry * dentry,
++ const struct vfsmount * mnt)
++{
++ __u32 mode;
++
++ if (unlikely(!dentry->d_inode))
++ return GR_FIND;
++
++ mode =
++ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt);
++
++ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) {
++ security_audit(GR_HIDDEN_ACL_MSG, "successful",
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++ return mode;
++ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) {
++ security_alert(GR_HIDDEN_ACL_MSG, "denied",
++ gr_to_filename(dentry, mnt),
++ DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely(!(mode & GR_FIND)))
++ return 0;
++
++ return GR_FIND;
++}
++
++__u32
++gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
++ const int fmode)
++{
++ __u32 reqmode = GR_FIND;
++ __u32 mode;
++
++ if (unlikely(!dentry->d_inode))
++ return reqmode;
++
++ if (unlikely(fmode & O_APPEND))
++ reqmode |= GR_APPEND;
++ else if (unlikely(fmode & FMODE_WRITE))
++ reqmode |= GR_WRITE;
++ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
++ reqmode |= GR_READ;
++
++ mode =
++ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
++ mnt);
++
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
++ security_audit(GR_OPEN_ACL_MSG, "successful",
++ gr_to_filename(dentry, mnt),
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" :
++ reqmode & GR_APPEND ? " appending" : "",
++ DEFAULTSECARGS);
++ return reqmode;
++ } else
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
++ {
++ security_alert(GR_OPEN_ACL_MSG, "denied",
++ gr_to_filename(dentry, mnt),
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : reqmode &
++ GR_APPEND ? " appending" : "", DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely((mode & reqmode) != reqmode))
++ return 0;
++
++ return reqmode;
++}
++
++__u32
++gr_acl_handle_creat(const struct dentry * dentry,
++ const struct dentry * p_dentry,
++ const struct vfsmount * p_mnt, const int fmode,
++ const int imode)
++{
++ __u32 reqmode = GR_WRITE | GR_CREATE;
++ __u32 mode;
++
++ if (unlikely(fmode & O_APPEND))
++ reqmode |= GR_APPEND;
++ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
++ reqmode |= GR_READ;
++ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID))))
++ reqmode |= GR_SETID;
++
++ mode =
++ gr_check_create(dentry, p_dentry, p_mnt,
++ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
++
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
++ security_audit(GR_CREATE_ACL_MSG, "successful",
++ gr_to_filename(dentry, p_mnt),
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" :
++ reqmode & GR_APPEND ? " appending" : "",
++ DEFAULTSECARGS);
++ return reqmode;
++ } else
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
++ {
++ security_alert(GR_CREATE_ACL_MSG, "denied",
++ gr_to_filename(dentry, p_mnt),
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : reqmode &
++ GR_APPEND ? " appending" : "", DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely((mode & reqmode) != reqmode))
++ return 0;
++
++ return reqmode;
++}
++
++__u32
++gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt,
++ const int fmode)
++{
++ __u32 mode, reqmode = GR_FIND;
++
++ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode))
++ reqmode |= GR_EXEC;
++ if (fmode & S_IWOTH)
++ reqmode |= GR_WRITE;
++ if (fmode & S_IROTH)
++ reqmode |= GR_READ;
++
++ mode =
++ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
++ mnt);
++
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
++ security_audit(GR_ACCESS_ACL_MSG, "successful",
++ gr_to_filename(dentry, mnt),
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : "",
++ reqmode & GR_EXEC ? " executing" : "",
++ DEFAULTSECARGS);
++ return reqmode;
++ } else
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
++ {
++ security_alert(GR_ACCESS_ACL_MSG, "denied",
++ gr_to_filename(dentry, mnt),
++ reqmode & GR_READ ? " reading" : "",
++ reqmode & GR_WRITE ? " writing" : "",
++ reqmode & GR_EXEC ? " executing" : "",
++ DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely((mode & reqmode) != reqmode))
++ return 0;
++
++ return reqmode;
++}
++
++#define generic_fs_handler(dentry, mnt, reqmode, fmt) \
++{ \
++ __u32 mode; \
++ \
++ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt); \
++ \
++ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) { \
++ security_audit(fmt, "successful", \
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS); \
++ return mode; \
++ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) { \
++ security_alert(fmt, "denied", gr_to_filename(dentry, mnt), \
++ DEFAULTSECARGS); \
++ return 0; \
++ } else if (unlikely((mode & (reqmode)) != (reqmode))) \
++ return 0; \
++ \
++ return (reqmode); \
++}
++
++__u32
++gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt,
++ mode_t mode)
++{
++ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
++ generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
++ GR_FCHMOD_ACL_MSG);
++ } else {
++ generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG);
++ }
++}
++
++__u32
++gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt,
++ mode_t mode)
++{
++ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
++ generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
++ GR_CHMOD_ACL_MSG);
++ } else {
++ generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG);
++ }
++}
++
++__u32
++gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE,
++ GR_UNIXCONNECT_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_filldir(const struct dentry *dentry, const struct vfsmount *mnt,
++ const ino_t ino)
++{
++ if (likely((unsigned long)(dentry->d_inode))) {
++ struct dentry d = *dentry;
++ struct inode inode = *(dentry->d_inode);
++
++ inode.i_ino = ino;
++ d.d_inode = &inode;
++
++ if (unlikely(!gr_search_file(&d, GR_FIND | GR_NOLEARN, mnt)))
++ return 0;
++ }
++
++ return 1;
++}
++
++__u32
++gr_acl_handle_link(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const struct dentry * old_dentry,
++ const struct vfsmount * old_mnt, const char *to)
++{
++ __u32 needmode = GR_WRITE | GR_CREATE;
++ __u32 mode;
++
++ mode =
++ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry,
++ old_mnt);
++
++ if (unlikely(((mode & needmode) == needmode) && mode & GR_AUDITS)) {
++ security_audit(GR_LINK_ACL_MSG, "successful",
++ gr_to_filename(old_dentry, old_mnt), to,
++ DEFAULTSECARGS);
++ return mode;
++ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
++ security_alert(GR_LINK_ACL_MSG, "denied",
++ gr_to_filename(old_dentry, old_mnt), to,
++ DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely((mode & needmode) != needmode))
++ return 0;
++
++ return (GR_WRITE | GR_CREATE);
++}
++
++__u32
++gr_acl_handle_symlink(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt, const char *from)
++{
++ __u32 needmode = GR_WRITE | GR_CREATE;
++ __u32 mode;
++
++ mode =
++ gr_check_create(new_dentry, parent_dentry, parent_mnt,
++ GR_CREATE | GR_AUDIT_CREATE |
++ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS);
++
++ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) {
++ security_audit(GR_SYMLINK_ACL_MSG, "successful",
++ from, gr_to_filename(new_dentry, parent_mnt),
++ DEFAULTSECARGS);
++ return mode;
++ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
++ security_alert(GR_SYMLINK_ACL_MSG, "denied",
++ from, gr_to_filename(new_dentry, parent_mnt),
++ DEFAULTSECARGS);
++ return 0;
++ } else if (unlikely((mode & needmode) != needmode))
++ return 0;
++
++ return (GR_WRITE | GR_CREATE);
++}
++
++#define generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt, reqmode, fmt) \
++{ \
++ __u32 mode; \
++ \
++ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS); \
++ \
++ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) { \
++ security_audit(fmt, "successful", \
++ gr_to_filename(new_dentry, parent_mnt), \
++ DEFAULTSECARGS); \
++ return mode; \
++ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) { \
++ security_alert(fmt, "denied", \
++ gr_to_filename(new_dentry, parent_mnt), \
++ DEFAULTSECARGS); \
++ return 0; \
++ } else if (unlikely((mode & (reqmode)) != (reqmode))) \
++ return 0; \
++ \
++ return (reqmode); \
++}
++
++__u32
++gr_acl_handle_mknod(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const int mode)
++{
++ __u32 reqmode = GR_WRITE | GR_CREATE;
++ if (unlikely(mode & (S_ISUID | S_ISGID)))
++ reqmode |= GR_SETID;
++
++ generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
++ reqmode, GR_MKNOD_ACL_MSG);
++}
++
++__u32
++gr_acl_handle_mkdir(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt)
++{
++ generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
++ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG);
++}
++
++#define RENAME_CHECK_SUCCESS(old, new) \
++ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \
++ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)))
++
++int
++gr_acl_handle_rename(struct dentry *new_dentry,
++ struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ struct dentry *old_dentry,
++ struct inode *old_parent_inode,
++ struct vfsmount *old_mnt, const char *newname)
++{
++ __u8 gr_replace = 1;
++ __u32 comp1, comp2;
++ int error = 0;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return 1;
++
++ if (!new_dentry->d_inode) {
++ gr_replace = 0;
++
++ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt,
++ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ |
++ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS);
++ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE |
++ GR_DELETE | GR_AUDIT_DELETE |
++ GR_AUDIT_READ | GR_AUDIT_WRITE |
++ GR_SUPPRESS, old_mnt);
++ } else {
++ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE |
++ GR_CREATE | GR_DELETE |
++ GR_AUDIT_CREATE | GR_AUDIT_DELETE |
++ GR_AUDIT_READ | GR_AUDIT_WRITE |
++ GR_SUPPRESS, parent_mnt);
++ comp2 =
++ gr_search_file(old_dentry,
++ GR_READ | GR_WRITE | GR_AUDIT_READ |
++ GR_DELETE | GR_AUDIT_DELETE |
++ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt);
++ }
++
++ if (RENAME_CHECK_SUCCESS(comp1, comp2) &&
++ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS)))
++ security_audit(GR_RENAME_ACL_MSG, "successful",
++ gr_to_filename(old_dentry, old_mnt),
++ newname, DEFAULTSECARGS);
++ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS)
++ && !(comp2 & GR_SUPPRESS)) {
++ security_alert(GR_RENAME_ACL_MSG, "denied",
++ gr_to_filename(old_dentry, old_mnt), newname,
++ DEFAULTSECARGS);
++ error = -EACCES;
++ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2)))
++ error = -EACCES;
++
++ if (error)
++ return error;
++
++ error = gr_handle_rename(old_parent_inode, parent_dentry->d_inode,
++ old_dentry, new_dentry, old_mnt, gr_replace);
++
++ return error;
++}
++
++void
++gr_acl_handle_exit(void)
++{
++ u16 id;
++ char *rolename;
++
++ if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) {
++ id = current->acl_role_id;
++ rolename = current->role->rolename;
++ gr_set_acls(1);
++ security_alert_good(GR_SPROLEL_ACL_MSG,
++ rolename, id, DEFAULTSECARGS);
++ }
++
++ if (current->exec_file) {
++ fput(current->exec_file);
++ current->exec_file = NULL;
++ }
++}
++
++int
++gr_acl_handle_procpidmem(const struct task_struct *task)
++{
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ if (task->acl->mode & GR_PROTPROCFD)
++ return -EACCES;
++
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/gracl_ip.c linux-2.4.21/grsecurity/gracl_ip.c
+--- linux-2.4.21/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_ip.c 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,235 @@
++/*
++ * grsecurity/gracl_ip.c
++ * Copyright Brad Spengler 2002, 2003
++ *
++ */
++
++#include <linux/kernel.h>
++#include <asm/uaccess.h>
++#include <asm/errno.h>
++#include <net/sock.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/udp.h>
++#include <linux/smp_lock.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++#define GR_BIND 0x01
++#define GR_CONNECT 0x02
++
++static const char * gr_protocols[256] = {
++ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt",
++ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet",
++ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1",
++ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp",
++ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++",
++ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre",
++ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile",
++ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63",
++ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv",
++ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak",
++ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf",
++ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp",
++ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim",
++ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip",
++ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp",
++ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup",
++ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135",
++ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143",
++ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151",
++ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159",
++ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167",
++ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175",
++ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183",
++ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191",
++ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199",
++ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207",
++ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215",
++ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223",
++ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231",
++ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239",
++ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247",
++ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255",
++ };
++
++static const char * gr_socktypes[11] = {
++ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6",
++ "unknown:7", "unknown:8", "unknown:9", "packet"
++ };
++
++static __inline__ const char *
++gr_proto_to_name(unsigned char proto)
++{
++ return gr_protocols[proto];
++}
++
++static __inline__ const char *
++gr_socktype_to_name(unsigned char type)
++{
++ return gr_socktypes[type];
++}
++
++int
++gr_search_socket(const int domain, const int type, const int protocol)
++{
++ struct acl_subject_label *curr;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ goto exit;
++
++ if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET)
++ || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255))
++ goto exit; // let the kernel handle it
++
++ curr = current->acl;
++
++ if (!curr->ips)
++ goto exit;
++
++ if ((curr->ip_type & (1 << type)) &&
++ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32))))
++ goto exit;
++
++ if (curr->mode & GR_LEARN) {
++ /* we don't place acls on raw sockets , and sometimes
++ dgram/ip sockets are opened for ioctl and not
++ bind/connect, so we'll fake a bind learn log */
++ if (type == SOCK_RAW || type == SOCK_PACKET) {
++ __u32 fakeip = 0;
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, current->uid,
++ current->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_dentry,
++ current->exec_file->f_vfsmnt) :
++ curr->filename, curr->filename,
++ NIPQUAD(fakeip), 0, type,
++ protocol, GR_CONNECT, NIPQUAD(current->curr_ip));
++ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
++ __u32 fakeip = 0;
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, current->uid,
++ current->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_dentry,
++ current->exec_file->f_vfsmnt) :
++ curr->filename, curr->filename,
++ NIPQUAD(fakeip), 0, type,
++ protocol, GR_BIND, NIPQUAD(current->curr_ip));
++ }
++ /* we'll log when they use connect or bind */
++ goto exit;
++ }
++
++ security_alert(GR_SOCK_MSG, "inet", gr_socktype_to_name(type),
++ gr_proto_to_name(protocol), DEFAULTSECARGS);
++
++ return 0;
++ exit:
++ return 1;
++}
++
++static __inline__ int
++gr_search_connectbind(const int mode, const struct sock *sk,
++ const struct sockaddr_in *addr, const int type)
++{
++ struct acl_subject_label *curr;
++ struct acl_ip_label *ip;
++ unsigned long i;
++ __u32 ip_addr = 0;
++ __u16 ip_port = 0;
++
++ if (unlikely(!gr_acl_is_enabled() || sk->family != PF_INET))
++ return 1;
++
++ curr = current->acl;
++
++ if (!curr->ips)
++ return 1;
++
++ ip_addr = addr->sin_addr.s_addr;
++ ip_port = ntohs(addr->sin_port);
++
++ for (i = 0; i < curr->ip_num; i++) {
++ ip = *(curr->ips + i);
++ if ((ip->mode & mode) &&
++ (ip_port >= ip->low) &&
++ (ip_port <= ip->high) &&
++ ((ntohl(ip_addr) & ip->netmask) ==
++ (ntohl(ip->addr) & ip->netmask))
++ && (ip->
++ proto[sk->protocol / 32] & (1 << (sk->protocol % 32)))
++ && (ip->type & (1 << type)))
++ return 1;
++ }
++
++ if (curr->mode & GR_LEARN) {
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
++ current->role->roletype, current->uid,
++ current->gid, current->exec_file ?
++ gr_to_filename(current->exec_file->f_dentry,
++ current->exec_file->f_vfsmnt) :
++ curr->filename, curr->filename,
++ NIPQUAD(ip_addr), ip_port, type,
++ sk->protocol, mode, NIPQUAD(current->curr_ip));
++ return 1;
++ }
++
++ if (mode == GR_BIND)
++ security_alert(GR_BIND_ACL_MSG, NIPQUAD(ip_addr), ip_port,
++ gr_socktype_to_name(type), gr_proto_to_name(sk->protocol),
++ DEFAULTSECARGS);
++ else if (mode == GR_CONNECT)
++ security_alert(GR_CONNECT_ACL_MSG, NIPQUAD(ip_addr), ip_port,
++ gr_socktype_to_name(type), gr_proto_to_name(sk->protocol),
++ DEFAULTSECARGS);
++
++ return 0;
++}
++
++int
++gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
++{
++ return gr_search_connectbind(GR_CONNECT, sock->sk, addr, sock->type);
++}
++
++int
++gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
++{
++ return gr_search_connectbind(GR_BIND, sock->sk, addr, sock->type);
++}
++
++int
++gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
++{
++ if (addr)
++ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM);
++ else {
++ struct sockaddr_in sin;
++
++ sin.sin_addr.s_addr = sk->daddr;
++ sin.sin_port = sk->dport;
++
++ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
++ }
++}
++
++int
++gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
++{
++ struct sockaddr_in sin;
++
++ if (unlikely(skb->len < sizeof (struct udphdr)))
++ return 1; // skip this packet
++
++ sin.sin_addr.s_addr = skb->nh.iph->saddr;
++ sin.sin_port = skb->h.uh->source;
++
++ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
++}
+diff -urN linux-2.4.21/grsecurity/gracl_learn.c linux-2.4.21/grsecurity/gracl_learn.c
+--- linux-2.4.21/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_learn.c 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,228 @@
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/smp_lock.h>
++#include <linux/string.h>
++#include <linux/file.h>
++#include <linux/types.h>
++#include <linux/vmalloc.h>
++#include <linux/grinternal.h>
++
++extern ssize_t write_grsec_handler(struct file * file, const char * buf,
++ size_t count, loff_t *ppos);
++extern int gr_acl_is_enabled(void);
++
++static DECLARE_WAIT_QUEUE_HEAD(learn_wait);
++static DECLARE_WAIT_QUEUE_HEAD(input_wait);
++static atomic_t learn_buffer_count = ATOMIC_INIT(0);
++static int gr_learn_attached;
++
++#define LEARN_BUFFER_SLOTS 256
++#define LEARN_BUFFER_SIZE 16384
++
++static spinlock_t learn_buffer_lock[LEARN_BUFFER_SLOTS] = { [0 ... (LEARN_BUFFER_SLOTS - 1)] = SPIN_LOCK_UNLOCKED };
++static char *learn_buffer[LEARN_BUFFER_SLOTS];
++static int learn_buffer_len[LEARN_BUFFER_SLOTS];
++
++static ssize_t
++read_learn(struct file *file, char * buf, size_t count, loff_t * ppos)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ ssize_t retval = 0;
++ char *tmp;
++ unsigned int len;
++ int i;
++
++ add_wait_queue(&learn_wait, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++ do {
++ if (atomic_read(&learn_buffer_count) > 1)
++ break;
++
++ if (file->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++
++ schedule();
++ } while (1);
++
++
++ for (i = 0; i < LEARN_BUFFER_SLOTS; i++) {
++ spin_lock(&learn_buffer_lock[i]);
++ len = learn_buffer_len[i];
++ tmp = learn_buffer[i];
++ if (!len || !tmp) {
++ spin_unlock(&learn_buffer_lock[i]);
++ continue;
++ }
++ learn_buffer[i] = NULL;
++ learn_buffer_len[i] = 0;
++ spin_unlock(&learn_buffer_lock[i]);
++
++ if (count < ((i * LEARN_BUFFER_SIZE) + len)) {
++ retval = -EINVAL;
++ vfree(tmp);
++ goto out;
++ }
++ if (copy_to_user(buf + (i * LEARN_BUFFER_SIZE), tmp, len)) {
++ retval = -EFAULT;
++ vfree(tmp);
++ goto out;
++ }
++
++ retval += len;
++ vfree(tmp);
++ atomic_dec(&learn_buffer_count);
++ atomic_dec(&learn_buffer_count);
++ }
++
++ wake_up(&input_wait);
++out:
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&learn_wait, &wait);
++ return retval;
++}
++
++static unsigned int
++poll_learn(struct file * file, poll_table * wait)
++{
++ poll_wait(file, &learn_wait, wait);
++
++ if (atomic_read(&learn_buffer_count) > 1)
++ return (POLLIN | POLLRDNORM);
++
++ return 0;
++}
++
++void
++gr_clear_learn_entries(void)
++{
++ int i;
++
++ atomic_set(&learn_buffer_count, 0);
++ wake_up(&input_wait);
++
++ for (i = 0; i < LEARN_BUFFER_SLOTS; i++) {
++ if (learn_buffer_len[i]) {
++ vfree(learn_buffer[i]);
++ learn_buffer[i] = NULL;
++ learn_buffer_len[i] = 0;
++ }
++ }
++
++ return;
++}
++
++void
++gr_add_learn_entry(const char *fmt, ...)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ va_list args;
++ char *tmpbuf;
++ char *buf;
++ int i;
++ unsigned int len;
++
++ if (!gr_learn_attached)
++ return;
++
++ tmpbuf = vmalloc(LEARN_BUFFER_SIZE);
++
++ if (tmpbuf == NULL)
++ return;
++
++ va_start(args, fmt);
++ len = vsnprintf(tmpbuf, LEARN_BUFFER_SIZE, fmt, args);
++ va_end(args);
++
++ if (len < 0)
++ len = LEARN_BUFFER_SIZE - 1;
++
++ buf = vmalloc(len + 1);
++
++ if (buf == NULL) {
++ vfree(tmpbuf);
++ return;
++ }
++
++ memcpy(buf, tmpbuf, len);
++ buf[len] = '\0';
++ vfree(tmpbuf);
++
++ add_wait_queue(&input_wait, &wait);
++
++ atomic_inc(&learn_buffer_count);
++ while (atomic_read(&learn_buffer_count) > ((2 * (LEARN_BUFFER_SLOTS - 1)) + 1)) {
++ /* don't sleep under the BKL */
++ if (unlikely(current->lock_depth >= 0)) {
++ remove_wait_queue(&input_wait, &wait);
++ atomic_dec(&learn_buffer_count);
++ vfree(buf);
++ return;
++ }
++ sleep_on(&input_wait);
++ }
++
++ if (!gr_acl_is_enabled()) {
++ remove_wait_queue(&input_wait, &wait);
++ atomic_dec(&learn_buffer_count);
++ vfree(buf);
++ return;
++ }
++
++ for (i = 0; i < LEARN_BUFFER_SLOTS; i++) {
++ spin_lock(&learn_buffer_lock[i]);
++
++ if (learn_buffer_len[i]) {
++ spin_unlock(&learn_buffer_lock[i]);
++ continue;
++ }
++
++ learn_buffer[i] = buf;
++
++ learn_buffer_len[i] = len + 1;
++
++ atomic_inc(&learn_buffer_count);
++ spin_unlock(&learn_buffer_lock[i]);
++ break;
++ }
++
++ remove_wait_queue(&input_wait, &wait);
++ wake_up_interruptible(&learn_wait);
++
++ return;
++}
++
++static int
++open_learn(struct inode *inode, struct file *file)
++{
++ if (file->f_mode & FMODE_READ && gr_learn_attached)
++ return -EBUSY;
++ else if (file->f_mode & FMODE_READ)
++ gr_learn_attached = 1;
++
++ return 0;
++}
++
++static int
++close_learn(struct inode *inode, struct file *file)
++{
++ if (file->f_mode & FMODE_READ)
++ gr_learn_attached = 0;
++
++ return 0;
++}
++
++struct file_operations grsec_fops = {
++ read: read_learn,
++ write: write_grsec_handler,
++ open: open_learn,
++ release: close_learn,
++ poll: poll_learn,
++};
+diff -urN linux-2.4.21/grsecurity/gracl_res.c linux-2.4.21/grsecurity/gracl_res.c
+--- linux-2.4.21/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_res.c 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,42 @@
++/* resource handling routines (c) Brad Spengler 2002, 2003 */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/gracl.h>
++#include <linux/grinternal.h>
++
++static const char *restab_log[11] = {
++ "RLIMIT_CPU",
++ "RLIMIT_FSIZE",
++ "RLIMIT_DATA",
++ "RLIMIT_STACK",
++ "RLIMIT_CORE",
++ "RLIMIT_RSS",
++ "RLIMIT_NPROC",
++ "RLIMIT_NOFILE",
++ "RLIMIT_MEMLOCK",
++ "RLIMIT_AS",
++ "RLIMIT_LOCKS"
++};
++
++__inline__ void
++gr_log_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted)
++{
++ if (unlikely(res == RLIMIT_NPROC &&
++ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) ||
++ cap_raised(task->cap_effective, CAP_SYS_RESOURCE))))
++ return;
++
++ if (unlikely(wanted >= task->rlim[res].rlim_cur &&
++ task->rlim[res].rlim_cur != RLIM_INFINITY))
++ security_alert(GR_RESOURCE_MSG, wanted, restab_log[res],
++ task->rlim[res].rlim_cur, task->comm,
++ task->pid, task->uid, task->euid,
++ task->gid, task->egid, task->p_pptr->comm,
++ task->p_pptr->pid, task->p_pptr->uid,
++ task->p_pptr->euid, task->p_pptr->gid,
++ task->p_pptr->egid);
++
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/gracl_segv.c linux-2.4.21/grsecurity/gracl_segv.c
+--- linux-2.4.21/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_segv.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,323 @@
++/*
++ * grsecurity/gracl_segv.c
++ * Copyright Brad Spengler 2002, 2003
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <asm/uaccess.h>
++#include <asm/errno.h>
++#include <asm/mman.h>
++#include <net/sock.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++static struct crash_uid *uid_set;
++static unsigned short uid_used;
++static rwlock_t gr_uid_lock = RW_LOCK_UNLOCKED;
++extern rwlock_t gr_inode_lock;
++extern __inline__ struct acl_subject_label *lookup_acl_subj_label(const ino_t
++ inode,
++ const kdev_t
++ dev,
++ struct
++ acl_role_label
++ *role);
++
++int
++gr_init_uidset(void)
++{
++ uid_set =
++ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL);
++ uid_used = 0;
++
++ return uid_set ? 1 : 0;
++}
++
++void
++gr_free_uidset(void)
++{
++ if (uid_set)
++ kfree(uid_set);
++
++ return;
++}
++
++int
++gr_find_uid(const uid_t uid)
++{
++ struct crash_uid *tmp = uid_set;
++ uid_t buid;
++ int low = 0, high = uid_used - 1, mid;
++
++ while (high >= low) {
++ mid = (low + high) >> 1;
++ buid = tmp[mid].uid;
++ if (buid == uid)
++ return mid;
++ if (buid > uid)
++ high = mid - 1;
++ if (buid < uid)
++ low = mid + 1;
++ }
++
++ return -1;
++}
++
++static __inline__ void
++gr_insertsort(void)
++{
++ unsigned short i, j;
++ struct crash_uid index;
++
++ for (i = 1; i < uid_used; i++) {
++ index = uid_set[i];
++ j = i;
++ while ((j > 0) && uid_set[j - 1].uid > index.uid) {
++ uid_set[j] = uid_set[j - 1];
++ j--;
++ }
++ uid_set[j] = index;
++ }
++
++ return;
++}
++
++static __inline__ void
++gr_insert_uid(const uid_t uid, const unsigned long expires)
++{
++ int loc;
++
++ if (uid_used == GR_UIDTABLE_MAX)
++ return;
++
++ loc = gr_find_uid(uid);
++
++ if (loc >= 0) {
++ uid_set[loc].expires = expires;
++ return;
++ }
++
++ uid_set[uid_used].uid = uid;
++ uid_set[uid_used].expires = expires;
++ uid_used++;
++
++ gr_insertsort();
++
++ return;
++}
++
++void
++gr_remove_uid(const unsigned short loc)
++{
++ unsigned short i;
++
++ for (i = loc + 1; i < uid_used; i++)
++ uid_set[i - i] = uid_set[i];
++
++ uid_used--;
++
++ return;
++}
++
++int
++gr_check_crash_uid(const uid_t uid)
++{
++ int loc;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ read_lock(&gr_uid_lock);
++ loc = gr_find_uid(uid);
++ read_unlock(&gr_uid_lock);
++
++ if (loc < 0)
++ return 0;
++
++ write_lock(&gr_uid_lock);
++ if (time_before_eq(uid_set[loc].expires, jiffies))
++ gr_remove_uid(loc);
++ else {
++ write_unlock(&gr_uid_lock);
++ return 1;
++ }
++
++ write_unlock(&gr_uid_lock);
++ return 0;
++}
++
++static __inline__ int
++proc_is_setxid(const struct task_struct *task)
++{
++ if (task->uid != task->euid || task->uid != task->suid ||
++ task->uid != task->fsuid)
++ return 1;
++ if (task->gid != task->egid || task->gid != task->sgid ||
++ task->gid != task->fsgid)
++ return 1;
++
++ return 0;
++}
++static __inline__ int
++gr_fake_force_sig(int sig, struct task_struct *t)
++{
++ unsigned long int flags;
++
++ spin_lock_irqsave(&t->sigmask_lock, flags);
++ if (t->sig == NULL) {
++ spin_unlock_irqrestore(&t->sigmask_lock, flags);
++ return -ESRCH;
++ }
++
++ if (t->sig->action[sig - 1].sa.sa_handler == SIG_IGN)
++ t->sig->action[sig - 1].sa.sa_handler = SIG_DFL;
++ sigdelset(&t->blocked, sig);
++ recalc_sigpending(t);
++ spin_unlock_irqrestore(&t->sigmask_lock, flags);
++
++ return send_sig_info(sig, (void *) 1L, t);
++}
++
++void
++gr_handle_crash(struct task_struct *task, const int sig)
++{
++ struct acl_subject_label *curr;
++ struct acl_subject_label *curr2;
++ struct task_struct *tsk;
++
++ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
++ return;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return;
++
++ curr = task->acl;
++
++ if (!(curr->resmask & (1 << GR_CRASH_RES)))
++ return;
++
++ if (time_before_eq(curr->expires, jiffies)) {
++ curr->expires = 0;
++ curr->crashes = 0;
++ }
++
++ curr->crashes++;
++
++ if (!curr->expires)
++ curr->expires = jiffies + curr->res[GR_CRASH_RES].rlim_max;
++
++ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
++ time_after(curr->expires, jiffies)) {
++ if (task->uid && proc_is_setxid(task)) {
++ security_alert(GR_SEGVSTART_ACL_MSG, task->comm,
++ task->pid, task->uid, task->euid,
++ task->gid, task->egid,
++ task->p_pptr->comm, task->p_pptr->pid,
++ task->p_pptr->uid, task->p_pptr->euid,
++ task->p_pptr->gid, task->p_pptr->egid,
++ task->uid,
++ curr->res[GR_CRASH_RES].rlim_max / HZ);
++ write_lock(&gr_uid_lock);
++ gr_insert_uid(task->uid, curr->expires);
++ write_unlock(&gr_uid_lock);
++ curr->expires = 0;
++ curr->crashes = 0;
++ read_lock(&tasklist_lock);
++ for_each_task(tsk) {
++ if (tsk != task && tsk->uid == task->uid)
++ gr_fake_force_sig(SIGKILL, tsk);
++ }
++ read_unlock(&tasklist_lock);
++ } else {
++ security_alert(GR_SEGVNOSUID_ACL_MSG, task->comm,
++ task->pid, task->uid, task->euid,
++ task->gid, task->egid,
++ task->p_pptr->comm, task->p_pptr->pid,
++ task->p_pptr->uid, task->p_pptr->euid,
++ task->p_pptr->gid, task->p_pptr->egid,
++ kdevname(curr->device), curr->inode,
++ curr->res[GR_CRASH_RES].rlim_max / HZ);
++ read_lock(&tasklist_lock);
++ for_each_task(tsk) {
++ if (likely(tsk != task)) {
++ curr2 = tsk->acl;
++
++ if (curr2->device == curr->device &&
++ curr2->inode == curr->inode)
++ gr_fake_force_sig(SIGKILL, tsk);
++ }
++ }
++ read_unlock(&tasklist_lock);
++ }
++ }
++
++ return;
++}
++
++int
++gr_check_crash_exec(const struct file *filp)
++{
++ struct acl_subject_label *curr;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return 0;
++
++ read_lock(&gr_inode_lock);
++ curr = lookup_acl_subj_label(filp->f_dentry->d_inode->i_ino,
++ filp->f_dentry->d_inode->i_dev,
++ current->role);
++ read_unlock(&gr_inode_lock);
++
++ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) ||
++ (!curr->crashes && !curr->expires))
++ return 0;
++
++ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
++ time_after(curr->expires, jiffies))
++ return 1;
++ else if (time_before_eq(curr->expires, jiffies)) {
++ curr->crashes = 0;
++ curr->expires = 0;
++ }
++
++ return 0;
++}
++
++void
++gr_handle_alertkill(void)
++{
++ struct acl_subject_label *curracl;
++ __u32 curr_ip;
++ struct task_struct *task;
++
++ if (unlikely(!gr_acl_is_enabled()))
++ return;
++
++ curracl = current->acl;
++ curr_ip = current->curr_ip;
++
++ if ((curracl->mode & GR_KILLIPPROC) && curr_ip &&
++ (curr_ip != 0xffffffff)) {
++ read_lock(&tasklist_lock);
++ for_each_task(task) {
++ if (task->curr_ip == curr_ip)
++ gr_fake_force_sig(SIGKILL, task);
++ }
++ read_unlock(&tasklist_lock);
++ } else if (curracl->mode & GR_KILLPROC)
++ gr_fake_force_sig(SIGKILL, current);
++
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/gracl_shm.c linux-2.4.21/grsecurity/gracl_shm.c
+--- linux-2.4.21/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/gracl_shm.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,36 @@
++/* shared memory handling routines, (c) Brad Spengler 2002, 2003 */
++
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/ipc.h>
++#include <linux/gracl.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime, const uid_t cuid, const int shmid)
++{
++ struct task_struct *task;
++
++ if (!gr_acl_is_enabled())
++ return 1;
++
++ task = find_task_by_pid(shm_cprid);
++
++ if (unlikely(!task))
++ task = find_task_by_pid(shm_lapid);
++
++ if (unlikely(task && ((task->start_time < shm_createtime) ||
++ (task->pid == shm_lapid)) &&
++ (task->acl->mode & GR_PROTSHM) &&
++ (task->acl != current->acl))) {
++ security_alert(GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid,
++ DEFAULTSECARGS);
++ return 0;
++ }
++
++ return 1;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_chdir.c linux-2.4.21/grsecurity/grsec_chdir.c
+--- linux-2.4.21/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_chdir.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,20 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
++ if ((grsec_enable_chdir && grsec_enable_group &&
++ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir &&
++ !grsec_enable_group)) {
++ security_audit(GR_CHDIR_AUDIT_MSG, gr_to_filename(dentry, mnt),
++ DEFAULTSECARGS);
++ }
++#endif
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_chroot.c linux-2.4.21/grsecurity/grsec_chroot.c
+--- linux-2.4.21/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_chroot.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,322 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/types.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_chroot_unix(const pid_t pid)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ struct task_struct *p, **htable;
++
++ if (unlikely(!grsec_enable_chroot_unix))
++ return 1;
++
++ if (likely(!proc_is_chrooted(current)))
++ return 1;
++
++ read_lock(&tasklist_lock);
++
++ htable = &pidhash[pid_hashfn(pid)];
++
++ for (p = *htable; p && p->pid != pid; p = p->pidhash_next) ;
++
++ if (unlikely(p && !have_same_root(current, p))) {
++ read_unlock(&tasklist_lock);
++ security_alert(GR_UNIX_CHROOT_MSG, DEFAULTSECARGS);
++ return 0;
++ }
++ read_unlock(&tasklist_lock);
++#endif
++ return 1;
++}
++
++int
++gr_handle_chroot_nice(void)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) {
++ security_alert(GR_NICE_CHROOT_MSG, DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_setpriority(task_t *p, const int niceval)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ if (grsec_enable_chroot_nice && (!have_same_root(p, current)
++ || (have_same_root(p, current)
++ && (niceval < task_nice(p))
++ && proc_is_chrooted(current)))) {
++ security_alert(GR_PRIORITY_CHROOT_MSG, p->comm, p->pid,
++ DEFAULTSECARGS);
++ return -ESRCH;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_capset(const struct task_struct *target)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ if (grsec_enable_chroot_caps && proc_is_chrooted(current) &&
++ !have_same_root(current, target)) {
++ security_alert(GR_CAPSET_CHROOT_MSG, target->comm, target->pid,
++ DEFAULTSECARGS);
++ return 1;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_pid_is_chrooted(const struct task_struct *p)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ if (!grsec_enable_chroot_findtask || (current->pid <= 1))
++ return 0;
++
++ if (p && p->fs && p->fs->root && p->fs->root->d_inode &&
++ child_reaper && child_reaper->fs && child_reaper->fs->root &&
++ child_reaper->fs->root->d_inode && current && current->fs &&
++ current->fs->root && current->fs->root->d_inode) {
++ if (proc_is_chrooted(current) && !have_same_root(current, p))
++ return 1;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
++ if (!grsec_enable_chroot_fchdir)
++ return 1;
++
++ if (!proc_is_chrooted(current))
++ return 1;
++ else {
++ struct dentry *dentry = u_dentry;
++ struct vfsmount *mnt = u_mnt;
++ struct dentry *realroot;
++ struct vfsmount *realrootmnt;
++ struct dentry *currentroot;
++ struct vfsmount *currentmnt;
++
++ read_lock(&child_reaper->fs->lock);
++ realrootmnt = mntget(child_reaper->fs->rootmnt);
++ realroot = dget(child_reaper->fs->root);
++ read_unlock(&child_reaper->fs->lock);
++
++ read_lock(¤t->fs->lock);
++ currentmnt = mntget(current->fs->rootmnt);
++ currentroot = dget(current->fs->root);
++ read_unlock(¤t->fs->lock);
++
++ spin_lock(&dcache_lock);
++ for (;;) {
++ if (unlikely
++ ((dentry == realroot && mnt == realrootmnt)
++ || (dentry == currentroot && mnt == currentmnt)))
++ break;
++ if (unlikely
++ (dentry == mnt->mnt_root || IS_ROOT(dentry))) {
++ if (mnt->mnt_parent == mnt)
++ break;
++ dentry = mnt->mnt_mountpoint;
++ mnt = mnt->mnt_parent;
++ continue;
++ }
++ dentry = dentry->d_parent;
++ }
++ spin_unlock(&dcache_lock);
++
++ dput(currentroot);
++ mntput(currentmnt);
++
++ if (dentry == realroot && mnt == realrootmnt) {
++ /* ok, they're definitely trying to fchdir outside of the
++ chroot. */
++ dput(realroot);
++ mntput(realrootmnt);
++ security_alert(GR_CHROOT_FCHDIR_MSG,
++ gr_to_filename(u_dentry, u_mnt),
++ DEFAULTSECARGS);
++ return 0;
++ } else {
++ dput(realroot);
++ mntput(realrootmnt);
++ return 1;
++ }
++ }
++#endif
++ return 1;
++}
++
++int
++gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
++ struct task_struct *p, **htable;
++
++ if (unlikely(!grsec_enable_chroot_shmat))
++ return 1;
++
++ if (likely(!proc_is_chrooted(current)))
++ return 1;
++
++ read_lock(&tasklist_lock);
++
++ htable = &pidhash[pid_hashfn(shm_cprid)];
++
++ for (p = *htable; p && p->pid != shm_cprid; p = p->pidhash_next) ;
++
++ if (unlikely(p && !have_same_root(current, p) &&
++ (p->start_time < shm_createtime))) {
++ read_unlock(&tasklist_lock);
++ security_alert(GR_SHMAT_CHROOT_MSG, DEFAULTSECARGS);
++ return 0;
++ }
++
++ if (unlikely(!p)) {
++ htable = &pidhash[pid_hashfn(shm_lapid)];
++ for (p = *htable; p && p->pid != shm_lapid;
++ p = p->pidhash_next) ;
++
++ if (unlikely(p && !have_same_root(current, p))) {
++ read_unlock(&tasklist_lock);
++ security_alert(GR_SHMAT_CHROOT_MSG, DEFAULTSECARGS);
++ return 0;
++ }
++ }
++
++ read_unlock(&tasklist_lock);
++#endif
++ return 1;
++}
++
++void
++gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
++ if (grsec_enable_chroot_execlog && proc_is_chrooted(current))
++ security_audit(GR_EXEC_CHROOT_MSG, gr_to_filename(dentry, mnt),
++ DEFAULTSECARGS);
++#endif
++ return;
++}
++
++int
++gr_handle_chroot_mknod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
++ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) &&
++ proc_is_chrooted(current)) {
++ security_alert(GR_MKNOD_CHROOT_MSG,
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_mount(const struct dentry *dentry,
++ const struct vfsmount *mnt, const char *dev_name)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
++ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) {
++ security_alert(GR_MOUNT_CHROOT_MSG, dev_name,
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_pivot(void)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
++ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) {
++ security_alert(GR_PIVOT_CHROOT_MSG, DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
++ if (grsec_enable_chroot_double && proc_is_chrooted(current)) {
++ security_alert(GR_CHROOT_CHROOT_MSG,
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
++
++void
++gr_handle_chroot_caps(struct task_struct *task)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) {
++ task->cap_permitted =
++ cap_drop(task->cap_permitted, GR_CHROOT_CAPS);
++ task->cap_inheritable =
++ cap_drop(task->cap_inheritable, GR_CHROOT_CAPS);
++ task->cap_effective =
++ cap_drop(task->cap_effective, GR_CHROOT_CAPS);
++ }
++#endif
++ return;
++}
++
++int
++gr_handle_chroot_sysctl(const int op)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
++ if (grsec_enable_chroot_sysctl && proc_is_chrooted(current)
++ && (op & 002))
++ return -EACCES;
++#endif
++ return 0;
++}
++
++void
++gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
++ if (grsec_enable_chroot_chdir)
++ set_fs_pwd(current->fs, mnt, dentry);
++#endif
++ return;
++}
++
++int
++gr_handle_chroot_chmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode)
++{
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
++ if (grsec_enable_chroot_chmod &&
++ ((mode & S_ISUID) || (mode & S_ISGID)) &&
++ proc_is_chrooted(current)) {
++ security_alert(GR_CHMOD_CHROOT_MSG,
++ gr_to_filename(dentry, mnt), DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_disabled.c linux-2.4.21/grsecurity/grsec_disabled.c
+--- linux-2.4.21/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_disabled.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,368 @@
++/*
++ * when grsecurity is disabled, compile all external functions into nothing
++ */
++
++#include <linux/kernel.h>
++#include <linux/config.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/kdev_t.h>
++#include <linux/net.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/skbuff.h>
++#include <linux/sysctl.h>
++
++#ifdef CONFIG_SYSCTL
++__u32
++gr_handle_sysctl(const struct ctl_table * table, __u32 mode)
++{
++ return mode;
++}
++#endif
++
++int
++gr_acl_is_enabled(void)
++{
++ return 0;
++}
++
++void
++gr_acl_handle_psacct(struct task_struct *task, const long code)
++{
++ return;
++}
++
++int
++gr_handle_ptrace_exec(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return 0;
++}
++
++int
++gr_handle_mmap(const struct file *filp, const unsigned long prot)
++{
++ return 0;
++}
++
++int
++gr_handle_ptrace(struct task_struct *task, const long request)
++{
++ return 0;
++}
++
++void
++gr_learn_resource(const struct task_struct *task,
++ const int res, const unsigned long wanted)
++{
++ return;
++}
++
++int
++gr_set_acls(const int type)
++{
++ return 0;
++}
++
++int
++gr_check_hidden_task(const struct task_struct *tsk)
++{
++ return 0;
++}
++
++int
++gr_check_protected_task(const struct task_struct *task)
++{
++ return 0;
++}
++
++__inline__ void
++gr_copy_label(struct task_struct *tsk)
++{
++ return;
++}
++
++void
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return;
++}
++
++void
++gr_handle_delete(const ino_t ino, const kdev_t dev)
++{
++ return;
++}
++
++void
++gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
++{
++ return;
++}
++
++void
++gr_handle_crash(struct task_struct *task, const int sig)
++{
++ return;
++}
++
++int
++gr_check_crash_exec(const struct file *filp)
++{
++ return 0;
++}
++
++int
++gr_check_crash_uid(const uid_t uid)
++{
++ return 0;
++}
++
++int
++gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
++ struct dentry *old_dentry,
++ struct dentry *new_dentry,
++ struct vfsmount *mnt, const __u8 replace)
++{
++ return 0;
++}
++
++int
++gr_search_socket(const int family, const int type, const int protocol)
++{
++ return 1;
++}
++
++int
++gr_search_connectbind(const int mode, const struct socket *sock,
++ const struct sockaddr_in *addr)
++{
++ return 1;
++}
++
++int
++gr_is_capable(const int cap)
++{
++ return 1;
++}
++
++void
++gr_handle_alertkill(void)
++{
++ return;
++}
++
++__u32
++gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_hidden_file(const struct dentry * dentry,
++ const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
++ const int fmode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++int
++gr_acl_handle_mmap(const struct file *file, const unsigned long prot,
++ unsigned int *vm_flags)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_truncate(const struct dentry * dentry,
++ const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_access(const struct dentry * dentry,
++ const struct vfsmount * mnt, const int fmode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt,
++ mode_t mode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt,
++ mode_t mode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++void
++grsecurity_init(void)
++{
++ return;
++}
++
++__u32
++gr_acl_handle_mknod(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const int mode)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_mkdir(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_symlink(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt, const char *from)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_link(const struct dentry * new_dentry,
++ const struct dentry * parent_dentry,
++ const struct vfsmount * parent_mnt,
++ const struct dentry * old_dentry,
++ const struct vfsmount * old_mnt, const char *to)
++{
++ return 1;
++}
++
++int
++gr_acl_handle_rename(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const struct dentry *old_dentry,
++ const struct inode *old_parent_inode,
++ const struct vfsmount *old_mnt, const char *newname)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_filldir(const struct dentry * dentry,
++ const struct vfsmount * mnt, const ino_t ino)
++{
++ return 1;
++}
++
++int
++gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime, const uid_t cuid, const int shmid)
++{
++ return 1;
++}
++
++int
++gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
++{
++ return 1;
++}
++
++int
++gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt)
++{
++ return 1;
++}
++
++__u32
++gr_acl_handle_creat(const struct dentry * dentry,
++ const struct dentry * p_dentry,
++ const struct vfsmount * p_mnt, const int fmode,
++ const int imode)
++{
++ return 1;
++}
++
++void
++gr_acl_handle_exit(void)
++{
++ return;
++}
++
++int
++gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
++{
++ return 1;
++}
++
++void
++gr_set_role_label(const uid_t uid, const gid_t gid)
++{
++ return;
++}
++
++int
++gr_acl_handle_procpidmem(const struct task_struct *task)
++{
++ return 0;
++}
++
++int
++gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
++{
++ return 1;
++}
++
++int
++gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
++{
++ return 1;
++}
++
++void
++gr_set_kernel_label(struct task_struct *task)
++{
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_exec.c linux-2.4.21/grsecurity/grsec_exec.c
+--- linux-2.4.21/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_exec.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,70 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/types.h>
++#include <linux/grdefs.h>
++#include <linux/grinternal.h>
++#include <linux/capability.h>
++
++#include <asm/uaccess.h>
++
++int
++gr_handle_nproc(void)
++{
++#ifdef CONFIG_GRKERNSEC_EXECVE
++ if (grsec_enable_execve && current->user &&
++ (atomic_read(¤t->user->processes) >
++ current->rlim[RLIMIT_NPROC].rlim_cur) &&
++ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
++ security_alert(GR_NPROC_MSG, DEFAULTSECARGS);
++ return -EAGAIN;
++ }
++#endif
++ return 0;
++}
++
++void
++gr_handle_exec_args(struct linux_binprm *bprm, char **argv)
++{
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ char grarg[64] = { 0 };
++ __u8 execlen = 0;
++ unsigned int i;
++
++ if (!((grsec_enable_execlog && grsec_enable_group &&
++ in_group_p(grsec_audit_gid))
++ || (grsec_enable_execlog && !grsec_enable_group)))
++ return;
++
++ if (unlikely(!argv))
++ goto log;
++
++ for (i = 0; i < bprm->argc && execlen < 62; i++) {
++ char *p;
++ __u8 len;
++
++ if (get_user(p, argv + i))
++ goto log;
++ if (!p)
++ goto log;
++ len = strnlen_user(p, 62 - execlen);
++ if (len > 62 - execlen)
++ len = 62 - execlen;
++ else if (len > 0)
++ len--;
++ if (copy_from_user(grarg + execlen, p, len))
++ goto log;
++ execlen += len;
++ *(grarg + execlen) = ' ';
++ *(grarg + execlen + 1) = '\0';
++ execlen++;
++ }
++
++ log:
++ security_audit(GR_EXEC_AUDIT_MSG, gr_to_filename(bprm->file->f_dentry,
++ bprm->file->f_vfsmnt),
++ grarg, DEFAULTSECARGS);
++#endif
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_fifo.c linux-2.4.21/grsecurity/grsec_fifo.c
+--- linux-2.4.21/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_fifo.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,24 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt,
++ const struct dentry *dir, const int flag, const int acc_mode)
++{
++#ifdef CONFIG_GRKERNSEC_FIFO
++ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
++ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
++ (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
++ (current->fsuid != dentry->d_inode->i_uid)) {
++ if (!permission(dentry->d_inode, acc_mode))
++ security_alert(GR_FIFO_MSG, gr_to_filename(dentry, mnt),
++ dentry->d_inode->i_uid,
++ dentry->d_inode->i_gid, DEFAULTSECARGS);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_fork.c linux-2.4.21/grsecurity/grsec_fork.c
+--- linux-2.4.21/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_fork.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,14 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_forkfail(const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_FORKFAIL
++ if (grsec_enable_forkfail)
++ security_alert(GR_FAILFORK_MSG, retval, DEFAULTSECARGS);
++#endif
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_init.c linux-2.4.21/grsecurity/grsec_init.c
+--- linux-2.4.21/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_init.c 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,199 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp_lock.h>
++
++int grsec_enable_link;
++int grsec_enable_dmesg;
++int grsec_enable_fifo;
++int grsec_enable_execve;
++int grsec_enable_execlog;
++int grsec_enable_signal;
++int grsec_enable_forkfail;
++int grsec_enable_time;
++int grsec_enable_group;
++int grsec_audit_gid;
++int grsec_enable_chdir;
++int grsec_enable_audit_ipc;
++int grsec_enable_mount;
++int grsec_enable_chroot_findtask;
++int grsec_enable_chroot_mount;
++int grsec_enable_chroot_shmat;
++int grsec_enable_chroot_fchdir;
++int grsec_enable_chroot_double;
++int grsec_enable_chroot_pivot;
++int grsec_enable_chroot_chdir;
++int grsec_enable_chroot_chmod;
++int grsec_enable_chroot_mknod;
++int grsec_enable_chroot_nice;
++int grsec_enable_chroot_execlog;
++int grsec_enable_chroot_caps;
++int grsec_enable_chroot_sysctl;
++int grsec_enable_chroot_unix;
++int grsec_enable_tpe;
++int grsec_tpe_gid;
++int grsec_enable_tpe_all;
++int grsec_enable_randpid;
++int grsec_enable_randid;
++int grsec_enable_randisn;
++int grsec_enable_randsrc;
++int grsec_enable_randrpc;
++int grsec_enable_socket_all;
++int grsec_socket_all_gid;
++int grsec_enable_socket_client;
++int grsec_socket_client_gid;
++int grsec_enable_socket_server;
++int grsec_socket_server_gid;
++int grsec_lock;
++
++spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED;
++unsigned long grsec_alert_wtime = 0;
++unsigned long grsec_alert_fyet = 0;
++
++spinlock_t grsec_alertgood_lock = SPIN_LOCK_UNLOCKED;
++unsigned long grsec_alertgood_wtime = 0;
++unsigned long grsec_alertgood_fyet = 0;
++
++spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED;
++
++char *gr_shared_page[2][NR_CPUS];
++
++extern void arc4_init(void);
++
++void
++grsecurity_init(void)
++{
++ int i, j;
++ /* create the per-cpu shared pages */
++
++ for (j = 0; j < 2; j++) {
++ for (i = 0; i < NR_CPUS; i++) {
++ gr_shared_page[j][i] = (char *) get_zeroed_page(GFP_KERNEL);
++ if (!gr_shared_page[j][i]) {
++ panic("Unable to allocate grsecurity shared page");
++ return;
++ }
++ }
++ }
++
++ arc4_init();
++
++#ifndef CONFIG_GRKERNSEC_SYSCTL
++ grsec_lock = 1;
++#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
++ grsec_enable_group = 1;
++ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
++ grsec_enable_chdir = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ grsec_enable_audit_ipc = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ grsec_enable_mount = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_LINK
++ grsec_enable_link = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_DMESG
++ grsec_enable_dmesg = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_FIFO
++ grsec_enable_fifo = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECVE
++ grsec_enable_execve = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ grsec_enable_execlog = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_SIGNAL
++ grsec_enable_signal = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_FORKFAIL
++ grsec_enable_forkfail = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_TIME
++ grsec_enable_time = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ grsec_enable_chroot_findtask = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ grsec_enable_chroot_unix = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
++ grsec_enable_chroot_mount = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
++ grsec_enable_chroot_fchdir = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
++ grsec_enable_chroot_shmat = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
++ grsec_enable_chroot_double = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
++ grsec_enable_chroot_pivot = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
++ grsec_enable_chroot_chdir = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
++ grsec_enable_chroot_chmod = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
++ grsec_enable_chroot_mknod = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ grsec_enable_chroot_nice = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
++ grsec_enable_chroot_execlog = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ grsec_enable_chroot_caps = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
++ grsec_enable_chroot_sysctl = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE
++ grsec_enable_tpe = 1;
++ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
++#ifdef CONFIG_GRKERNSEC_TPE_ALL
++ grsec_enable_tpe_all = 1;
++#endif
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDPID
++ grsec_enable_randpid = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDID
++ grsec_enable_randid = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDISN
++ grsec_enable_randisn = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDSRC
++ grsec_enable_randsrc = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDRPC
++ grsec_enable_randrpc = 1;
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
++ grsec_enable_socket_all = 1;
++ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
++ grsec_enable_socket_client = 1;
++ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ grsec_enable_socket_server = 1;
++ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
++#endif
++#endif
++
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_ipc.c linux-2.4.21/grsecurity/grsec_ipc.c
+--- linux-2.4.21/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_ipc.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,81 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/ipc.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_msgget(const int ret, const int msgflg)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
++ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
++ !grsec_enable_group)) && (ret >= 0)
++ && (msgflg & IPC_CREAT))
++ security_audit(GR_MSGQ_AUDIT_MSG, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_msgrm(const uid_t uid, const uid_t cuid)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
++ grsec_enable_audit_ipc) ||
++ (grsec_enable_audit_ipc && !grsec_enable_group))
++ security_audit(GR_MSGQR_AUDIT_MSG, uid, cuid, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_semget(const int err, const int semflg)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
++ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
++ !grsec_enable_group)) && (err >= 0)
++ && (semflg & IPC_CREAT))
++ security_audit(GR_SEM_AUDIT_MSG, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_semrm(const uid_t uid, const uid_t cuid)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
++ grsec_enable_audit_ipc) ||
++ (grsec_enable_audit_ipc && !grsec_enable_group))
++ security_audit(GR_SEMR_AUDIT_MSG, uid, cuid, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_shmget(const int err, const int shmflg, const size_t size)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
++ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
++ !grsec_enable_group)) && (err >= 0)
++ && (shmflg & IPC_CREAT))
++ security_audit(GR_SHM_AUDIT_MSG, size, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_shmrm(const uid_t uid, const uid_t cuid)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
++ grsec_enable_audit_ipc) ||
++ (grsec_enable_audit_ipc && !grsec_enable_group))
++ security_audit(GR_SHMR_AUDIT_MSG, uid, cuid, DEFAULTSECARGS);
++#endif
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_link.c linux-2.4.21/grsecurity/grsec_link.c
+--- linux-2.4.21/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_link.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,41 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_follow_link(const struct inode *parent,
++ const struct inode *inode,
++ const struct dentry *dentry, const struct vfsmount *mnt)
++{
++#ifdef CONFIG_GRKERNSEC_LINK
++ if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
++ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
++ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) {
++ security_alert(GR_SYMLINK_MSG, gr_to_filename(dentry, mnt),
++ inode->i_uid, inode->i_gid, DEFAULTSECARGS);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_hardlink(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ struct inode *inode, const int mode, const char *to)
++{
++#ifdef CONFIG_GRKERNSEC_LINK
++ if (grsec_enable_link && current->fsuid != inode->i_uid &&
++ (!S_ISREG(mode) || (mode & S_ISUID) ||
++ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
++ (permission(inode, MAY_READ | MAY_WRITE))) &&
++ !capable(CAP_FOWNER) && current->uid) {
++ security_alert(GR_HARDLINK_MSG, gr_to_filename(dentry, mnt),
++ inode->i_uid, inode->i_gid, to, DEFAULTSECARGS);
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_mem.c linux-2.4.21/grsecurity/grsec_mem.c
+--- linux-2.4.21/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_mem.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,54 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/grinternal.h>
++
++void
++gr_handle_ioperm(void)
++{
++ security_alert(GR_IOPERM_MSG, DEFAULTSECARGS);
++ return;
++}
++
++void
++gr_handle_iopl(void)
++{
++ security_alert(GR_IOPL_MSG, DEFAULTSECARGS);
++ return;
++}
++
++void
++gr_handle_mem_write(void)
++{
++ security_alert(GR_MEM_WRITE_MSG, DEFAULTSECARGS);
++ return;
++}
++
++void
++gr_handle_kmem_write(void)
++{
++ security_alert(GR_KMEM_MSG, DEFAULTSECARGS);
++ return;
++}
++
++void
++gr_handle_open_port(void)
++{
++ security_alert(GR_PORT_OPEN_MSG, DEFAULTSECARGS);
++ return;
++}
++
++int
++gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma)
++{
++ if (offset < __pa(high_memory) &&
++ (pgprot_val(vma->vm_page_prot) & PROT_WRITE) &&
++ (offset != 0xa0000 || ((vma->vm_end - vma->vm_start) > 0x20000))) {
++ security_alert(GR_MEM_MMAP_MSG, DEFAULTSECARGS);
++ return -EPERM;
++ } else if (offset < __pa(high_memory))
++ vma->vm_flags &= ~VM_MAYWRITE;
++
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_mount.c linux-2.4.21/grsecurity/grsec_mount.c
+--- linux-2.4.21/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_mount.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,34 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_remount(const char *devname, const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ if (grsec_enable_mount && (retval >= 0))
++ security_audit(GR_REMOUNT_AUDIT_MSG, devname, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_unmount(const char *devname, const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ if (grsec_enable_mount && (retval >= 0))
++ security_audit(GR_UNMOUNT_AUDIT_MSG, devname, DEFAULTSECARGS);
++#endif
++ return;
++}
++
++void
++gr_log_mount(const char *from, const char *to, const int retval)
++{
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ if (grsec_enable_mount && (retval >= 0))
++ security_audit(GR_MOUNT_AUDIT_MSG, from, to, DEFAULTSECARGS);
++#endif
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_rand.c linux-2.4.21/grsecurity/grsec_rand.c
+--- linux-2.4.21/grsecurity/grsec_rand.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_rand.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,36 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++extern int last_pid;
++
++int
++gr_random_pid(spinlock_t * pid_lock)
++{
++#ifdef CONFIG_GRKERNSEC_RANDPID
++ struct task_struct *p;
++ int pid;
++
++ if (grsec_enable_randpid && current->fs->root) {
++ read_lock(&tasklist_lock);
++ spin_lock(pid_lock);
++
++ repeater:
++
++ pid = 1 + (arc4random() % PID_MAX);
++
++ for_each_task(p) {
++ if (p->pid == pid || p->pgrp == pid ||
++ p->tgid == pid || p->session == pid)
++ goto repeater;
++ }
++ last_pid = pid;
++ spin_unlock(pid_lock);
++ read_unlock(&tasklist_lock);
++ return pid;
++ }
++#endif
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_sig.c linux-2.4.21/grsecurity/grsec_sig.c
+--- linux-2.4.21/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_sig.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,43 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_signal(const int sig, const struct task_struct *t)
++{
++#ifdef CONFIG_GRKERNSEC_SIGNAL
++ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) ||
++ (sig == SIGABRT) || (sig == SIGBUS))) {
++ if (t->pid == current->pid) {
++ security_alert_good(GR_UNISIGLOG_MSG, sig,
++ DEFAULTSECARGS);
++ } else {
++ security_alert_good(GR_DUALSIGLOG_MSG, sig, t->comm,
++ t->pid, t->uid, t->euid, t->gid,
++ t->egid, t->p_pptr->comm,
++ t->p_pptr->pid, t->p_pptr->uid,
++ t->p_pptr->euid, t->p_pptr->gid,
++ t->p_pptr->egid, DEFAULTSECARGS);
++ }
++ }
++#endif
++ return;
++}
++
++int
++gr_handle_signal(const struct task_struct *p, const int sig)
++{
++#ifdef CONFIG_GRKERNSEC
++ if (current->pid > 1 && gr_check_protected_task(p)) {
++ security_alert(GR_SIG_ACL_MSG, sig, p->comm, p->pid, p->uid,
++ p->euid, p->gid, p->egid, p->p_pptr->comm,
++ p->p_pptr->pid, p->p_pptr->uid,
++ p->p_pptr->euid, p->p_pptr->gid,
++ p->p_pptr->egid, DEFAULTSECARGS);
++ return -EPERM;
++ } else if (gr_pid_is_chrooted(p)) {
++ return -EPERM;
++ }
++#endif
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_sock.c linux-2.4.21/grsecurity/grsec_sock.c
+--- linux-2.4.21/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_sock.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,123 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/net.h>
++#include <net/sock.h>
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++#include <linux/gracl.h>
++
++void
++gr_attach_curr_ip(const struct sock *sk)
++{
++#ifdef CONFIG_GRKERNSEC
++ struct task_struct *p;
++ unsigned int i;
++ struct inode *inode;
++ struct file *filp;
++ struct socket *connect_sock;
++
++ if (unlikely(sk->protocol != IPPROTO_TCP))
++ return;
++
++ read_lock(&tasklist_lock);
++ for_each_task(p) {
++ if (!p->used_connect)
++ continue;
++ task_lock(p);
++ if (unlikely(!p->files)) {
++ task_unlock(p);
++ continue;
++ }
++ read_lock(&p->files->file_lock);
++ for (i = 0; i < p->files->max_fds; i++) {
++ filp = fcheck_files(p->files, i);
++ if (likely(!filp))
++ continue;
++ inode = filp->f_dentry->d_inode;
++ if (likely(!inode || !inode->i_sock))
++ continue;
++ connect_sock = &inode->u.socket_i;
++ if (unlikely(!connect_sock ||
++ connect_sock->sk->protocol != IPPROTO_TCP))
++ continue;
++ if (unlikely(sk->rcv_saddr == connect_sock->sk->daddr &&
++ sk->daddr == connect_sock->sk->rcv_saddr &&
++ ntohs(sk->sport) ==
++ ntohs(connect_sock->sk->dport)
++ && ntohs(sk->dport) ==
++ ntohs(connect_sock->sk->sport))) {
++ current->curr_ip = p->curr_ip;
++ current->used_accept = 1;
++ read_unlock(&p->files->file_lock);
++ task_unlock(p);
++ read_unlock(&tasklist_lock);
++ return;
++ }
++ }
++ read_unlock(&p->files->file_lock);
++ task_unlock(p);
++ }
++ read_unlock(&tasklist_lock);
++
++ current->curr_ip = sk->daddr;
++ current->used_accept = 1;
++#endif
++ return;
++}
++
++int
++gr_handle_sock_all(const int family, const int type, const int protocol)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
++ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
++ (family != AF_UNIX) && (family != AF_LOCAL)) {
++ security_alert(GR_SOCK_MSG, family, type, protocol,
++ DEFAULTSECARGS);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_sock_server(const struct sockaddr *sck)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ if (grsec_enable_socket_server &&
++ in_group_p(grsec_socket_server_gid) &&
++ sck && (sck->sa_family != AF_UNIX) &&
++ (sck->sa_family != AF_LOCAL)) {
++ security_alert(GR_BIND_MSG, DEFAULTSECARGS);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++int
++gr_handle_sock_client(const struct sockaddr *sck)
++{
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
++ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
++ sck && (sck->sa_family != AF_UNIX) &&
++ (sck->sa_family != AF_LOCAL)) {
++ security_alert(GR_CONNECT_MSG, DEFAULTSECARGS);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
++
++__u32
++gr_cap_rtnetlink(void)
++{
++#ifdef CONFIG_GRKERNSEC
++ if (!gr_acl_is_enabled())
++ return current->cap_effective;
++ else
++ return (current->cap_effective & ~(current->acl->cap_lower));
++#else
++ return current->cap_effective;
++#endif
++}
+diff -urN linux-2.4.21/grsecurity/grsec_sysctl.c linux-2.4.21/grsecurity/grsec_sysctl.c
+--- linux-2.4.21/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_sysctl.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,16 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/sysctl.h>
++#include <linux/grinternal.h>
++
++int
++gr_handle_sysctl_mod(const char *dirname, const char *name, const int op)
++{
++#ifdef CONFIG_GRKERNSEC_SYSCTL
++ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & 002)) {
++ security_alert(GR_SYSCTL_MSG, name, DEFAULTSECARGS);
++ return -EACCES;
++ }
++#endif
++ return 0;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_time.c linux-2.4.21/grsecurity/grsec_time.c
+--- linux-2.4.21/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_time.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,13 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/grinternal.h>
++
++void
++gr_log_timechange(void)
++{
++#ifdef CONFIG_GRKERNSEC_TIME
++ if (grsec_enable_time)
++ security_alert_good(GR_TIME_MSG, DEFAULTSECARGS);
++#endif
++ return;
++}
+diff -urN linux-2.4.21/grsecurity/grsec_tpe.c linux-2.4.21/grsecurity/grsec_tpe.c
+--- linux-2.4.21/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsec_tpe.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,33 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/file.h>
++#include <linux/fs.h>
++#include <linux/grinternal.h>
++
++int
++gr_tpe_allow(const struct file *file)
++{
++#ifdef CONFIG_GRKERNSEC_TPE
++ struct inode *inode = file->f_dentry->d_parent->d_inode;
++
++ if (current->uid && grsec_enable_tpe && in_group_p(grsec_tpe_gid) &&
++ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) ||
++ (inode->i_mode & S_IWOTH))))) {
++ security_alert(GR_EXEC_TPE_MSG,
++ gr_to_filename(file->f_dentry, file->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 0;
++ }
++#ifdef CONFIG_GRKERNSEC_TPE_ALL
++ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
++ ((inode->i_uid && (inode->i_uid != current->uid)) ||
++ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
++ security_alert(GR_EXEC_TPE_MSG,
++ gr_to_filename(file->f_dentry, file->f_vfsmnt),
++ DEFAULTSECARGS);
++ return 0;
++ }
++#endif
++#endif
++ return 1;
++}
+diff -urN linux-2.4.21/grsecurity/grsum.c linux-2.4.21/grsecurity/grsum.c
+--- linux-2.4.21/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/grsum.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,297 @@
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/gracl.h>
++
++/* digest-sha256.c,v 1.13 2002/10/02 22:02:08 hvr Exp $
++ *
++ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
++ *
++ * Glue code originally by Andrew McDonald and Alan Smithee, mailed
++ * to maintainer on pulped trees.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, or (at your option) any
++ * later version.
++ *
++ */
++
++typedef struct {
++ __u32 state[8];
++ __u32 count[2];
++ __u8 buf[128];
++} sha256_ctx_t;
++
++static __inline__ __u32
++generic_rotr32(const __u32 x, const unsigned bits)
++{
++ const unsigned n = bits % 32;
++ return (x >> n) | (x << (32 - n));
++}
++
++#define Ch(x,y,z) ((x & y) ^ (~x & z))
++#define Maj(x,y,z) ((x & y) ^ ( x & z) ^ (y & z))
++#define RORu32(x,y) generic_rotr32(x, y)
++#define e0(x) (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22))
++#define e1(x) (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25))
++#define s0(x) (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3))
++#define s1(x) (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10))
++
++#define H0 0x6a09e667
++#define H1 0xbb67ae85
++#define H2 0x3c6ef372
++#define H3 0xa54ff53a
++#define H4 0x510e527f
++#define H5 0x9b05688c
++#define H6 0x1f83d9ab
++#define H7 0x5be0cd19
++
++const static __u32 sha256_K[64] = {
++ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
++ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
++ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
++ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
++ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
++ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
++ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
++ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
++ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
++ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
++ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
++ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
++ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
++ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
++ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
++ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
++};
++
++#define LOAD_OP(I)\
++ {\
++ t1 = input[(4*I) ] & 0xff; t1<<=8;\
++ t1 |= input[(4*I)+1] & 0xff; t1<<=8;\
++ t1 |= input[(4*I)+2] & 0xff; t1<<=8;\
++ t1 |= input[(4*I)+3] & 0xff;\
++ W[I] = t1;\
++ }
++
++#define BLEND_OP(I) W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
++
++static void
++SHA256Transform(__u32 * state, const __u8 * input)
++{
++ __u32 a, b, c, d, e, f, g, h, t1, t2;
++ __u32 W[64];
++
++ int i;
++
++ /* load the input */
++ LOAD_OP(0);
++ LOAD_OP(1);
++ LOAD_OP(2);
++ LOAD_OP(3);
++ LOAD_OP(4);
++ LOAD_OP(5);
++ LOAD_OP(6);
++ LOAD_OP(7);
++ LOAD_OP(8);
++ LOAD_OP(9);
++ LOAD_OP(10);
++ LOAD_OP(11);
++ LOAD_OP(12);
++ LOAD_OP(13);
++ LOAD_OP(14);
++ LOAD_OP(15);
++
++ /* now blend */
++ for (i = 16; i < 64; i += 8) {
++ BLEND_OP(i);
++ BLEND_OP(i + 1);
++ BLEND_OP(i + 2);
++ BLEND_OP(i + 3);
++ BLEND_OP(i + 4);
++ BLEND_OP(i + 5);
++ BLEND_OP(i + 6);
++ BLEND_OP(i + 7);
++ }
++
++ /* load the state into our registers */
++ a = state[0];
++ b = state[1];
++ c = state[2];
++ d = state[3];
++ e = state[4];
++ f = state[5];
++ g = state[6];
++ h = state[7];
++
++ /* now iterate */
++ for (i = 0; i < 64; i += 8) {
++ t1 = h + e1(e) + Ch(e, f, g) + sha256_K[i] + W[i];
++ t2 = e0(a) + Maj(a, b, c);
++ d += t1;
++ h = t1 + t2;
++ t1 = g + e1(d) + Ch(d, e, f) + sha256_K[i + 1] + W[i + 1];
++ t2 = e0(h) + Maj(h, a, b);
++ c += t1;
++ g = t1 + t2;
++ t1 = f + e1(c) + Ch(c, d, e) + sha256_K[i + 2] + W[i + 2];
++ t2 = e0(g) + Maj(g, h, a);
++ b += t1;
++ f = t1 + t2;
++ t1 = e + e1(b) + Ch(b, c, d) + sha256_K[i + 3] + W[i + 3];
++ t2 = e0(f) + Maj(f, g, h);
++ a += t1;
++ e = t1 + t2;
++ t1 = d + e1(a) + Ch(a, b, c) + sha256_K[i + 4] + W[i + 4];
++ t2 = e0(e) + Maj(e, f, g);
++ h += t1;
++ d = t1 + t2;
++ t1 = c + e1(h) + Ch(h, a, b) + sha256_K[i + 5] + W[i + 5];
++ t2 = e0(d) + Maj(d, e, f);
++ g += t1;
++ c = t1 + t2;
++ t1 = b + e1(g) + Ch(g, h, a) + sha256_K[i + 6] + W[i + 6];
++ t2 = e0(c) + Maj(c, d, e);
++ f += t1;
++ b = t1 + t2;
++ t1 = a + e1(f) + Ch(f, g, h) + sha256_K[i + 7] + W[i + 7];
++ t2 = e0(b) + Maj(b, c, d);
++ e += t1;
++ a = t1 + t2;
++ }
++
++ state[0] += a;
++ state[1] += b;
++ state[2] += c;
++ state[3] += d;
++ state[4] += e;
++ state[5] += f;
++ state[6] += g;
++ state[7] += h;
++
++ /* clear any sensitive info... */
++ a = b = c = d = e = f = g = h = t1 = t2 = 0;
++ memset(W, 0, 64 * sizeof (__u32));
++}
++
++static void
++SHA256Init(sha256_ctx_t * C)
++{
++ C->state[0] = H0;
++ C->state[1] = H1;
++ C->state[2] = H2;
++ C->state[3] = H3;
++ C->state[4] = H4;
++ C->state[5] = H5;
++ C->state[6] = H6;
++ C->state[7] = H7;
++ C->count[0] = C->count[1] = 0;
++ memset(C->buf, 0, 128);
++}
++
++static void
++SHA256Update(sha256_ctx_t * C, const __u8 * input, __u32 inputLen)
++{
++ __u32 i, index, partLen;
++
++ /* Compute number of bytes mod 128 */
++ index = (__u32) ((C->count[0] >> 3) & 0x3f);
++
++ /* Update number of bits */
++ if ((C->count[0] += (inputLen << 3)) < (inputLen << 3)) {
++ C->count[1]++;
++ C->count[1] += (inputLen >> 29);
++ }
++
++ partLen = 64 - index;
++
++ /* Transform as many times as possible. */
++ if (inputLen >= partLen) {
++ memcpy(&C->buf[index], input, partLen);
++ SHA256Transform(C->state, C->buf);
++
++ for (i = partLen; i + 63 < inputLen; i += 64)
++ SHA256Transform(C->state, &input[i]);
++ index = 0;
++ } else {
++ i = 0;
++ }
++
++ /* Buffer remaining input */
++ memcpy(&C->buf[index], &input[i], inputLen - i);
++}
++
++static void
++SHA256Final(sha256_ctx_t * C, __u8 * digest)
++{
++ const static __u8 padding[64] = { 0x80, };
++ __u8 bits[8];
++ __u32 t, index, padLen;
++ int i, j;
++
++ /* Save number of bits */
++ t = C->count[0];
++ bits[7] = t;
++ t >>= 8;
++ bits[6] = t;
++ t >>= 8;
++ bits[5] = t;
++ t >>= 8;
++ bits[4] = t;
++ t = C->count[1];
++ bits[3] = t;
++ t >>= 8;
++ bits[2] = t;
++ t >>= 8;
++ bits[1] = t;
++ t >>= 8;
++ bits[0] = t;
++
++ /* Pad out to 56 mod 64. */
++ index = (C->count[0] >> 3) & 0x3f;
++ padLen = (index < 56) ? (56 - index) : ((64 + 56) - index);
++ SHA256Update(C, padding, padLen);
++
++ /* Append length (before padding) */
++ SHA256Update(C, bits, sizeof (bits));
++
++ /* Store state in digest */
++ for (i = j = 0; i < 8; i++, j += 4) {
++ t = C->state[i];
++ digest[j + 3] = t;
++ t >>= 8;
++ digest[j + 2] = t;
++ t >>= 8;
++ digest[j + 1] = t;
++ t >>= 8;
++ digest[j] = t;
++ }
++
++ /* Zeroize sensitive information. */
++ memset(C, 0, sizeof (sha256_ctx_t));
++}
++
++int
++chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum)
++{
++ sha256_ctx_t context;
++ unsigned char temp_sum[GR_SHA_LEN];
++ volatile int retval = 0;
++ volatile int dummy = 0;
++ unsigned int i;
++
++ SHA256Init(&context);
++ SHA256Update(&context, salt, GR_SALT_LEN);
++ SHA256Update(&context, entry->pw, strlen(entry->pw));
++ SHA256Final(&context, temp_sum);
++
++ memset(entry->pw, 0, GR_PW_LEN);
++
++ for (i = 0; i < GR_SHA_LEN; i++)
++ if (sum[i] != temp_sum[i])
++ retval = 1;
++ else
++ dummy = 1; // waste a cycle
++
++ return retval;
++}
+diff -urN linux-2.4.21/grsecurity/obsd_rand.c linux-2.4.21/grsecurity/obsd_rand.c
+--- linux-2.4.21/grsecurity/obsd_rand.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/grsecurity/obsd_rand.c 2003-06-23 11:49:16.000000000 -0400
+@@ -0,0 +1,299 @@
++
++/*
++ * Copyright (c) 1996, 1997, 2000-2002 Michael Shalayeff.
++ *
++ * Version 1.89, last modified 19-Sep-99
++ *
++ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.
++ * All rights reserved.
++ *
++ * Copyright 1998 Niels Provos <provos@citi.umich.edu>
++ * All rights reserved.
++ * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
++ * such a mathematical system to generate more random (yet non-repeating)
++ * ids to solve the resolver/named problem. But Niels designed the
++ * actual system based on the constraints.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer,
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by Niels Provos.
++ * 4. The name of the author may not be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++#include <linux/smp_lock.h>
++#include <linux/random.h>
++
++#define RU_OUT 180
++#define RU_MAX 30000
++#define RU_GEN 2
++#define RU_N 32749
++#define RU_AGEN 7
++#define RU_M 31104
++#define PFAC_N 3
++const static __u16 pfacts[PFAC_N] = { 2, 3, 2729 };
++
++static __u16 ru_x;
++static __u16 ru_seed, ru_seed2;
++static __u16 ru_a, ru_b;
++static __u16 ru_g;
++static __u16 ru_counter = 0;
++static __u16 ru_msb = 0;
++static unsigned long ru_reseed = 0;
++static __u32 tmp;
++
++static struct arc4_stream {
++ __u8 s[256];
++ unsigned int cnt;
++ __u8 i;
++ __u8 j;
++} arc4random_state[NR_CPUS];
++
++#define TCP_RNDISS_ROUNDS 15
++#define TCP_RNDISS_OUT 7200
++#define TCP_RNDISS_MAX 30000
++
++static __u8 tcp_rndiss_sbox[NR_CPUS][128];
++static __u16 tcp_rndiss_msb[NR_CPUS];
++static __u16 tcp_rndiss_cnt[NR_CPUS];
++static unsigned long tcp_rndiss_reseed[NR_CPUS];
++
++static unsigned long arc4random_reseed[NR_CPUS];
++
++static int arc4random_initialized[NR_CPUS];
++
++static __u16 pmod(__u16, __u16, __u16);
++static void ip_initid(void);
++__u16 ip_randomid(void);
++
++static __inline__ __u8 arc4_getbyte(void);
++static __inline__ void arc4_stir(void);
++static void arc4maybeinit(void);
++__u32 arc4random(void);
++
++static __inline__ __u8
++arc4_getbyte(void)
++{
++ register __u8 si, sj;
++ int cpu = smp_processor_id();
++
++ arc4random_state[cpu].cnt++;
++ arc4random_state[cpu].i++;
++ si = arc4random_state[cpu].s[arc4random_state[cpu].i];
++ arc4random_state[cpu].j += si;
++ sj = arc4random_state[cpu].s[arc4random_state[cpu].j];
++ arc4random_state[cpu].s[arc4random_state[cpu].i] = sj;
++ arc4random_state[cpu].s[arc4random_state[cpu].j] = si;
++ return arc4random_state[cpu].s[(si + sj) & 0xff];
++}
++
++static __inline__ void
++arc4_stir(void)
++{
++ __u8 buf[256];
++ register __u8 si;
++ register int n;
++ int len = sizeof (buf);
++ int cpu = smp_processor_id();
++ unsigned long flags;
++
++ do_gettimeofday((struct timeval *) buf);
++ get_random_bytes(buf + sizeof (struct timeval),
++ len - sizeof (struct timeval));
++
++ save_flags(flags);
++ cli();
++
++ arc4random_state[cpu].i--;
++ for (n = 0; n < 256; n++) {
++ arc4random_state[cpu].i++;
++ si = arc4random_state[cpu].s[arc4random_state[cpu].i];
++ arc4random_state[cpu].j += si + buf[n % len];
++ arc4random_state[cpu].s[arc4random_state[cpu].i] =
++ arc4random_state[cpu].s[arc4random_state[cpu].j];
++ arc4random_state[cpu].s[arc4random_state[cpu].j] = si;
++ }
++ arc4random_state[cpu].j = arc4random_state[cpu].i;
++ arc4random_state[cpu].cnt = 0;
++
++ restore_flags(flags);
++
++ for (n = 0; n < 256 * 4; n++)
++ arc4_getbyte();
++
++ return;
++}
++
++void
++arc4_init(void)
++{
++ int i, n;
++
++ for (n = 0; n < NR_CPUS; n++) {
++ for (i = 0; i < 256; i++)
++ arc4random_state[n].s[i] = i;
++ arc4random_initialized[n] = 0;
++ }
++}
++
++static void
++arc4maybeinit(void)
++{
++ int cpu = smp_processor_id();
++
++ if (arc4random_initialized[cpu] &&
++ time_after(xtime.tv_sec, arc4random_reseed[cpu]))
++ arc4random_initialized[cpu] = 0;
++
++ if (!arc4random_initialized[cpu]) {
++ arc4random_initialized[cpu]++;
++ arc4_stir();
++ arc4random_reseed[cpu] = xtime.tv_sec + (10 * 60);
++ }
++}
++
++__u32
++arc4random(void)
++{
++ arc4maybeinit();
++ return ((arc4_getbyte() << 24) | (arc4_getbyte() << 16)
++ | (arc4_getbyte() << 8) | arc4_getbyte());
++}
++
++static __u16
++pmod(__u16 gen, __u16 exp, __u16 mod)
++{
++ __u16 s, t, u;
++
++ s = 1;
++ t = gen;
++ u = exp;
++
++ while (u) {
++ if (u & 1)
++ s = (s * t) % mod;
++ u >>= 1;
++ t = (t * t) % mod;
++ }
++ return (s);
++}
++
++static void
++ip_initid(void)
++{
++ __u16 j, i;
++ int noprime = 1;
++
++ ru_x = ((tmp = arc4random()) & 0xFFFF) % RU_M;
++
++ ru_seed = (tmp >> 16) & 0x7FFF;
++ ru_seed2 = arc4random() & 0x7FFF;
++
++ ru_b = ((tmp = arc4random()) & 0xfffe) | 1;
++ ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
++ while (ru_b % 3 == 0)
++ ru_b += 2;
++
++ j = (tmp = arc4random()) % RU_N;
++ tmp = tmp >> 16;
++
++ while (noprime) {
++ for (i = 0; i < PFAC_N; i++)
++ if (j % pfacts[i] == 0)
++ break;
++
++ if (i >= PFAC_N)
++ noprime = 0;
++ else
++ j = (j + 1) % RU_N;
++ }
++
++ ru_g = pmod(RU_GEN, j, RU_N);
++ ru_counter = 0;
++
++ ru_reseed = xtime.tv_sec + RU_OUT;
++ ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
++}
++
++__u16
++ip_randomid(void)
++{
++ int i, n;
++
++ if (ru_counter >= RU_MAX || time_after(xtime.tv_sec, ru_reseed))
++ ip_initid();
++
++ if (!tmp)
++ tmp = arc4random();
++
++ n = tmp & 0x3;
++ tmp = tmp >> 2;
++ if (ru_counter + n >= RU_MAX)
++ ip_initid();
++ for (i = 0; i <= n; i++)
++ ru_x = (ru_a * ru_x + ru_b) % RU_M;
++ ru_counter += i;
++
++ return ((ru_seed ^ pmod(ru_g, ru_seed2 ^ ru_x, RU_N)) | ru_msb);
++}
++
++__u16
++tcp_rndiss_encrypt(__u16 val)
++{
++ __u16 sum = 0, i;
++ int cpu = smp_processor_id();
++
++ for (i = 0; i < TCP_RNDISS_ROUNDS; i++) {
++ sum += 0x79b9;
++ val ^= ((__u16) tcp_rndiss_sbox[cpu][(val ^ sum) ^ 0x7f]) << 7;
++ val = ((val & 0xff) << 7) | (val >> 8);
++ }
++
++ return val;
++}
++
++static void
++tcp_rndiss_init(void)
++{
++ int cpu = smp_processor_id();
++
++ get_random_bytes(tcp_rndiss_sbox[cpu], sizeof (tcp_rndiss_sbox));
++ tcp_rndiss_reseed[cpu] = xtime.tv_sec + TCP_RNDISS_OUT;
++ tcp_rndiss_msb[cpu] = tcp_rndiss_msb[cpu] == 0x8000 ? 0 : 0x8000;
++ tcp_rndiss_cnt[cpu] = 0;
++}
++
++__u32
++ip_randomisn(void)
++{
++ int cpu = smp_processor_id();
++
++ if (tcp_rndiss_cnt[cpu] >= TCP_RNDISS_MAX ||
++ time_after(xtime.tv_sec, tcp_rndiss_reseed[cpu]))
++ tcp_rndiss_init();
++
++ return (((tcp_rndiss_encrypt(tcp_rndiss_cnt[cpu]++) |
++ tcp_rndiss_msb[cpu]) << 16) | (arc4random() & 0x7fff));
++}
+diff -urN linux-2.4.21/include/linux/fs.h linux-2.4.21/include/linux/fs.h
+--- linux-2.4.21/include/linux/fs.h 2003-06-23 11:41:32.000000000 -0400
++++ linux-2.4.21/include/linux/fs.h 2003-06-23 11:49:17.000000000 -0400
+@@ -1070,7 +1070,7 @@
+
+ asmlinkage long sys_open(const char *, int, int);
+ asmlinkage long sys_close(unsigned int); /* yes, it's really unsigned */
+-extern int do_truncate(struct dentry *, loff_t start);
++extern int do_truncate(struct dentry *, loff_t start, struct vfsmount *);
+
+ extern struct file *filp_open(const char *, int, int);
+ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
+diff -urN linux-2.4.21/include/linux/gracl.h linux-2.4.21/include/linux/gracl.h
+--- linux-2.4.21/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/include/linux/gracl.h 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,211 @@
++#ifndef GR_ACL_H
++#define GR_ACL_H
++#endif
++#include <linux/grdefs.h>
++#include <linux/resource.h>
++
++#include <asm/resource.h>
++
++/* * * * * * * * * * * * * * * * * * * * *
++ * grsecurity ACL System
++ * Main header file
++ * Purpose: define most gracl data structures
++ * * * * * * * * * * * * * * * * * * * * */
++
++/* Major status information */
++
++#define GR_VERSION "grsecurity 2.0"
++
++enum {
++
++ SHUTDOWN = 0,
++ ENABLE = 1,
++ SPROLE = 2,
++ RELOAD = 3,
++ SEGVMOD = 4,
++ STATUS = 5
++};
++
++/* Password setup definitions
++ * kernel/grhash.c */
++enum {
++ GR_PW_LEN = 128,
++ GR_SALT_LEN = 16,
++ GR_SHA_LEN = 32,
++};
++
++enum {
++ GR_SPROLE_LEN = 64,
++};
++
++/* Begin Data Structures */
++
++struct sprole_pw {
++ unsigned char *rolename;
++ unsigned char salt[GR_SALT_LEN];
++ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */
++};
++
++struct name_entry {
++ ino_t inode;
++ kdev_t device;
++ char *name;
++ __u16 len;
++};
++
++struct acl_role_db {
++ struct acl_role_label **r_hash;
++ __u32 r_size;
++};
++
++struct name_db {
++ struct name_entry **n_hash;
++ __u32 n_size;
++};
++
++struct crash_uid {
++ uid_t uid;
++ unsigned long expires;
++};
++
++/* Userspace Grsecurity ACL data structures */
++struct acl_subject_label {
++ char *filename;
++ ino_t inode;
++ kdev_t device;
++ __u32 mode;
++ __u32 cap_raise;
++ __u32 cap_lower;
++
++ struct rlimit res[RLIM_NLIMITS + 1];
++ __u16 resmask;
++
++ __u32 ip_proto[8];
++ __u32 ip_type;
++ struct acl_ip_label **ips;
++ __u32 ip_num;
++
++ __u32 crashes;
++ unsigned long expires;
++
++ struct acl_subject_label *parent_subject;
++ struct acl_object_label *proc_object;
++ struct acl_ip_label *ip_object;
++ struct acl_subject_label *prev;
++ struct acl_subject_label *next;
++
++ struct acl_object_label **obj_hash;
++ __u32 obj_hash_size;
++};
++
++struct role_allowed_ip {
++ __u32 addr;
++ __u32 netmask;
++
++ struct role_allowed_ip *prev;
++ struct role_allowed_ip *next;
++};
++
++struct role_transition {
++ char *rolename;
++
++ struct role_transition *prev;
++ struct role_transition *next;
++};
++
++struct acl_role_label {
++ char *rolename;
++ uid_t uidgid;
++ __u16 roletype;
++
++ __u16 auth_attempts;
++ unsigned long expires;
++
++ struct acl_subject_label *root_label;
++ struct acl_subject_label *proc_subject;
++
++ struct acl_role_label *prev;
++ struct acl_role_label *next;
++
++ struct role_transition *transitions;
++ struct role_allowed_ip *allowed_ips;
++ struct acl_subject_label **subj_hash;
++ __u32 subj_hash_size;
++};
++
++struct user_acl_role_db {
++ struct acl_role_label **r_table;
++ __u32 r_entries; /* number of entries in table */
++ __u32 s_entries; /* total number of subject acls */
++ __u32 i_entries; /* total number of ip acls */
++ __u32 o_entries; /* Total number of object acls */
++ __u32 a_entries; /* total number of allowed ips */
++ __u32 t_entries; /* total number of transitions */
++};
++
++struct acl_object_label {
++ char *filename;
++ ino_t inode;
++ kdev_t device;
++ __u32 mode;
++
++ struct acl_subject_label *nested;
++
++ /* next two structures not used */
++
++ struct acl_object_label *prev;
++ struct acl_object_label *next;
++};
++
++struct acl_ip_label {
++ __u32 addr;
++ __u32 netmask;
++ __u16 low, high;
++ __u8 mode;
++ __u32 type;
++ __u32 proto[8];
++
++ /* next two structures not used */
++
++ struct acl_ip_label *prev;
++ struct acl_ip_label *next;
++};
++
++struct gr_arg {
++ struct user_acl_role_db role_db;
++ unsigned char pw[GR_PW_LEN];
++ unsigned char salt[GR_SALT_LEN];
++ unsigned char sum[GR_SHA_LEN];
++ unsigned char sp_role[GR_SPROLE_LEN];
++ struct sprole_pw *sprole_pws;
++ __u16 num_sprole_pws;
++ kdev_t segv_device;
++ ino_t segv_inode;
++ uid_t segv_uid;
++ __u16 mode;
++};
++
++/* End Data Structures Section */
++
++/* Hash functions generated by empirical testing by Brad Spengler
++ Makes good use of the low bits of the inode. Generally 0-1 times
++ in loop for successful match. 0-3 for unsuccessful match.
++ Shift/add algorithm with modulus of table size and an XOR*/
++
++static __inline__ unsigned long
++rhash(const uid_t uid, const __u16 type, const unsigned long sz)
++{
++ return (((uid << type) + (uid ^ type)) % sz);
++}
++
++static __inline__ unsigned long
++fhash(const ino_t ino, const kdev_t dev, const unsigned long sz)
++{
++ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz);
++}
++
++static __inline__ unsigned long
++nhash(const char *name, const __u16 len, const unsigned long sz)
++{
++ return full_name_hash(name, len) % sz;
++}
+diff -urN linux-2.4.21/include/linux/gralloc.h linux-2.4.21/include/linux/gralloc.h
+--- linux-2.4.21/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/include/linux/gralloc.h 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,8 @@
++#ifndef __GRALLOC_H
++#define __GRALLOC_H
++
++void acl_free_all(void);
++int acl_alloc_stack_init(unsigned long size);
++void *acl_alloc(unsigned long len);
++
++#endif
+diff -urN linux-2.4.21/include/linux/grdefs.h linux-2.4.21/include/linux/grdefs.h
+--- linux-2.4.21/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/include/linux/grdefs.h 2003-06-23 11:49:17.000000000 -0400
+@@ -0,0 +1,96 @@
++#ifndef GRDEFS_H
++#define GRDEFS_H
++
++/* Begin grsecurity status declarations */
++
++enum {
++ GR_READY = 0x01,
++ GR_STATUS_INIT = 0x00 // disabled state
++};
++
++/* Begin ACL declarations */
++
++/* Role flags */
++
++enum {
++ GR_ROLE_USER = 0x0001,
++ GR_ROLE_GROUP = 0x0002,
++ GR_ROLE_DEFAULT = 0x0004,
++ GR_ROLE_SPECIAL = 0x0008,
++ GR_ROLE_AUTH = 0x0010,
++ GR_ROLE_NOPW = 0x0020,
++ GR_ROLE_GOD = 0x0040
++};
++
++/* ACL Subject and Object mode flags */
++enum {
++ GR_DELETED = 0x00000080
++};
++
++/* ACL Object-only mode flags */
++enum {
++ GR_READ = 0x00000001,
++ GR_APPEND = 0x00000002,
++ GR_WRITE = 0x00000004,
++ GR_EXEC = 0x00000008,
++ GR_FIND = 0x00000010,
++ GR_INHERIT = 0x00000040,
++ GR_PTRACERD = 0x00000100,
++ GR_SETID = 0x00000200,
++ GR_CREATE = 0x00000400,
++ GR_DELETE = 0x00000800,
++ GR_AUDIT_READ = 0x00001000,
++ GR_AUDIT_APPEND = 0x00002000,
++ GR_AUDIT_WRITE = 0x0004000,
++ GR_AUDIT_EXEC = 0x00008000,
++ GR_AUDIT_FIND = 0x00010000,
++ GR_AUDIT_INHERIT = 0x00020000,
++ GR_AUDIT_SETID = 0x00400000,
++ GR_AUDIT_CREATE = 0x00800000,
++ GR_AUDIT_DELETE = 0x01000000,
++ GR_SUPPRESS = 0x02000000,
++ GR_NOLEARN = 0x04000000
++};
++
++#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
++ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
++ GR_AUDIT_CREATE | GR_AUDIT_DELETE)
++
++/* ACL subject-only mode flags */
++enum {
++ GR_KILL = 0x00000001,
++ GR_VIEW = 0x00000002,
++ GR_PROTECTED = 0x00000100,
++ GR_LEARN = 0x00000200,
++ GR_OVERRIDE = 0x00000400,
++ /* just a placeholder, this mode is only used in userspace */
++ GR_DUMMY = 0x00000800,
++
++ GR_PROTSHM = 0x00040000,
++ GR_KILLPROC = 0x00080000,
++ GR_KILLIPPROC = 0x00100000,
++ /* just a placeholder, this mode is only used in userspace */
++ GR_NOTROJAN = 0x00200000,
++ GR_PROTPROCFD = 0x00400000,
++ GR_PROCACCT = 0x00800000
++};
++
++#define GR_CRASH_RES 11
++#define GR_UIDTABLE_MAX 500
++
++/* begin resource learning section */
++enum {
++ GR_RLIM_CPU_BUMP = 60,
++ GR_RLIM_FSIZE_BUMP = 50000,
++ GR_RLIM_DATA_BUMP = 10000,
++ GR_RLIM_STACK_BUMP = 1000,
++ GR_RLIM_CORE_BUMP = 10000,
++ GR_RLIM_RSS_BUMP = 500000,
++ GR_RLIM_NPROC_BUMP = 1,
++ GR_RLIM_NOFILE_BUMP = 5,
++ GR_RLIM_MEMLOCK_BUMP = 50000,
++ GR_RLIM_AS_BUMP = 500000,
++ GR_RLIM_LOCKS_BUMP = 2
++};
++
++#endif
+diff -urN linux-2.4.21/include/linux/grinternal.h linux-2.4.21/include/linux/grinternal.h
+--- linux-2.4.21/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/include/linux/grinternal.h 2003-06-23 11:49:17.000000000 -0400
+@@ -0,0 +1,177 @@
++#ifndef __GRINTERNAL_H
++#define __GRINTERNAL_H
++
++#ifdef CONFIG_GRKERNSEC
++
++#include <linux/grdefs.h>
++#include <linux/grmsg.h>
++
++extern void gr_add_learn_entry(const char *fmt, ...);
++extern __u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
++ const struct vfsmount *mnt);
++extern __u32 gr_check_create(const struct dentry *new_dentry,
++ const struct dentry *parent,
++ const struct vfsmount *mnt, const __u32 mode);
++extern int gr_check_protected_task(const struct task_struct *task);
++extern __inline__ __u32 to_gr_audit(const __u32 reqmode);
++extern int gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
++ struct dentry *old_dentry,
++ struct dentry *new_dentry,
++ struct vfsmount *mnt, const __u8 replace);
++extern int gr_set_acls(const int type);
++
++extern void gr_handle_alertkill(void);
++extern char *gr_to_filename(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++
++extern int grsec_enable_link;
++extern int grsec_enable_fifo;
++extern int grsec_enable_execve;
++extern int grsec_enable_forkbomb;
++extern int grsec_forkbomb_gid;
++extern int grsec_forkbomb_sec;
++extern int grsec_forkbomb_max;
++extern int grsec_enable_execlog;
++extern int grsec_enable_signal;
++extern int grsec_enable_forkfail;
++extern int grsec_enable_time;
++extern int grsec_enable_chroot_shmat;
++extern int grsec_enable_chroot_findtask;
++extern int grsec_enable_chroot_mount;
++extern int grsec_enable_chroot_double;
++extern int grsec_enable_chroot_pivot;
++extern int grsec_enable_chroot_chdir;
++extern int grsec_enable_chroot_chmod;
++extern int grsec_enable_chroot_mknod;
++extern int grsec_enable_chroot_fchdir;
++extern int grsec_enable_chroot_nice;
++extern int grsec_enable_chroot_execlog;
++extern int grsec_enable_chroot_caps;
++extern int grsec_enable_chroot_sysctl;
++extern int grsec_enable_chroot_unix;
++extern int grsec_enable_tpe;
++extern int grsec_tpe_gid;
++extern int grsec_enable_tpe_all;
++extern int grsec_enable_sidcaps;
++extern int grsec_enable_randpid;
++extern int grsec_enable_socket_all;
++extern int grsec_socket_all_gid;
++extern int grsec_enable_socket_client;
++extern int grsec_socket_client_gid;
++extern int grsec_enable_socket_server;
++extern int grsec_socket_server_gid;
++extern int grsec_audit_gid;
++extern int grsec_enable_group;
++extern int grsec_enable_audit_ipc;
++extern int grsec_enable_mount;
++extern int grsec_enable_chdir;
++extern int grsec_lock;
++
++extern struct task_struct *child_reaper;
++
++extern spinlock_t grsec_alert_lock;
++extern unsigned long grsec_alert_wtime;
++extern unsigned long grsec_alert_fyet;
++
++extern spinlock_t grsec_alertgood_lock;
++extern unsigned long grsec_alertgood_wtime;
++extern unsigned long grsec_alertgood_fyet;
++
++extern spinlock_t grsec_audit_lock;
++
++#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && \
++ ((tsk_a->fs->root->d_inode->i_dev != \
++ child_reaper->fs->root->d_inode->i_dev) || \
++ (tsk_a->fs->root->d_inode->i_ino != \
++ child_reaper->fs->root->d_inode->i_ino)))
++
++#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs->root->d_inode->i_dev == \
++ tsk_b->fs->root->d_inode->i_dev) && \
++ (tsk_a->fs->root->d_inode->i_ino == \
++ tsk_b->fs->root->d_inode->i_ino))
++
++#define DEFAULTSECARGS current->comm, current->pid, current->uid, \
++ current->euid, current->gid, current->egid, \
++ current->p_pptr->comm, current->p_pptr->pid, \
++ current->p_pptr->uid, current->p_pptr->euid, \
++ current->p_pptr->gid, current->p_pptr->egid
++
++#define GR_CHROOT_CAPS ( \
++ CAP_TO_MASK(CAP_FOWNER) | \
++ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
++ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
++ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
++ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
++ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
++ CAP_TO_MASK(CAP_IPC_OWNER))
++
++#define security_alert_good(normal_msg,args...) \
++({ \
++ spin_lock(&grsec_alertgood_lock); \
++ \
++ if (!grsec_alertgood_wtime || jiffies - grsec_alertgood_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) { \
++ grsec_alertgood_wtime = jiffies; grsec_alertgood_fyet = 0; \
++ if (current->curr_ip) \
++ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \
++ else \
++ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \
++ } else if((jiffies - grsec_alertgood_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alertgood_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { \
++ grsec_alertgood_fyet++; \
++ if (current->curr_ip) \
++ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \
++ else \
++ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \
++ } else if (grsec_alertgood_fyet == CONFIG_GRKERNSEC_FLOODBURST) { \
++ grsec_alertgood_wtime = jiffies; grsec_alertgood_fyet++; \
++ printk(KERN_ALERT "grsec: more alerts, logging disabled for " \
++ "%d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); \
++ } \
++ \
++ spin_unlock(&grsec_alertgood_lock); \
++})
++
++#define security_alert(normal_msg,args...) \
++({ \
++ spin_lock(&grsec_alert_lock); \
++ \
++ if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) { \
++ grsec_alert_wtime = jiffies; grsec_alert_fyet = 0; \
++ if (current->curr_ip) \
++ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \
++ else \
++ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \
++ } else if((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { \
++ grsec_alert_fyet++; \
++ if (current->curr_ip) \
++ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \
++ else \
++ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \
++ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) { \
++ grsec_alert_wtime = jiffies; grsec_alert_fyet++; \
++ printk(KERN_ALERT "grsec: more alerts, logging disabled for " \
++ "%d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); \
++ } \
++ \
++ gr_handle_alertkill(); \
++ spin_unlock(&grsec_alert_lock); \
++})
++
++#define security_audit(normal_msg,args...) \
++({ \
++ spin_lock(&grsec_audit_lock); \
++ if (current->curr_ip) \
++ printk(KERN_INFO "grsec: From %u.%u.%u.%u: " normal_msg "\n", \
++ NIPQUAD(current->curr_ip) , ## args); \
++ else \
++ printk(KERN_INFO "grsec: " normal_msg "\n", ## args); \
++ spin_unlock(&grsec_audit_lock); \
++})
++
++#define security_learn(normal_msg,args...) \
++({ \
++ gr_add_learn_entry(normal_msg "\n", ## args); \
++})
++
++#endif
++
++#endif
+diff -urN linux-2.4.21/include/linux/grmsg.h linux-2.4.21/include/linux/grmsg.h
+--- linux-2.4.21/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/include/linux/grmsg.h 2003-06-23 11:49:17.000000000 -0400
+@@ -0,0 +1,101 @@
++#define DEFAULTSECMSG "(%.16s:%d) uid/euid:%d/%d gid/egid:%d/%d, parent (%.16s:%d) uid/euid:%d/%d gid/egid:%d/%d"
++#define GR_ACL_PROCACCT_MSG "(%.16s:%d) IP:%u.%u.%u.%u TTY:%.64s uid/euid:%d/%d gid/egid:%d/%d run time:[%ud %uh %um %us] cpu time:[%ud %uh %um %us] %s with exit code %ld, parent (%.16s:%d) IP:%u.%u.%u.%u TTY:%.64s uid/euid:%d/%d gid/egid:%d/%d"
++#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by " DEFAULTSECMSG
++#define GR_IOPERM_MSG "denied use of ioperm() by " DEFAULTSECMSG
++#define GR_IOPL_MSG "denied use of iopl() by " DEFAULTSECMSG
++#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by " DEFAULTSECMSG
++#define GR_UNIX_CHROOT_MSG "denied connect to abstract AF_UNIX socket outside of chroot by " DEFAULTSECMSG
++#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by " DEFAULTSECMSG
++#define GR_KMEM_MSG "attempted write to /dev/kmem by " DEFAULTSECMSG
++#define GR_PORT_OPEN_MSG "attempted open of /dev/port by " DEFAULTSECMSG
++#define GR_MEM_WRITE_MSG "attempted write of /dev/mem by " DEFAULTSECMSG
++#define GR_MEM_MMAP_MSG "attempted mmap write of /dev/[k]mem by " DEFAULTSECMSG
++#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by " DEFAULTSECMSG
++#define GR_LEARN_AUDIT_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%lu\t%lu\t%.4095s\t%lu\t%u.%u.%u.%u"
++#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by " DEFAULTSECMSG
++#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by " DEFAULTSECMSG
++#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by " DEFAULTSECMSG
++#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by " DEFAULTSECMSG
++#define GR_MKNOD_CHROOT_MSG "refused attempt to mknod %.950s from chroot by " DEFAULTSECMSG
++#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by " DEFAULTSECMSG
++#define GR_UNIXCONNECT_ACL_MSG "%s connect to the unix domain socket %.950s by " DEFAULTSECMSG
++#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by " DEFAULTSECMSG
++#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by " DEFAULTSECMSG
++#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by " DEFAULTSECMSG
++#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by " DEFAULTSECMSG
++#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for " DEFAULTSECMSG
++#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by " DEFAULTSECMSG
++#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by " DEFAULTSECMSG
++#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by " DEFAULTSECMSG
++#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by " DEFAULTSECMSG
++#define GR_NPROC_MSG "attempt to overstep process limit by " DEFAULTSECMSG
++#define GR_EXEC_ACL_MSG "%s execution of %.950s by " DEFAULTSECMSG
++#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by " DEFAULTSECMSG
++#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " Banning uid %u from login for %lu seconds"
++#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " Banning execution of [%.16s:%lu] for %lu seconds"
++#define GR_MOUNT_CHROOT_MSG "denied attempt to mount %.30s as %.930s from chroot by " DEFAULTSECMSG
++#define GR_PIVOT_CHROOT_MSG "denied attempt to pivot_root from chroot by " DEFAULTSECMSG
++#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by " DEFAULTSECMSG
++#define GR_ATIME_ACL_MSG "%s access time change of %.950s by " DEFAULTSECMSG
++#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by " DEFAULTSECMSG
++#define GR_CHROOT_CHROOT_MSG "denied attempt to double chroot to %.950s by " DEFAULTSECMSG
++#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by " DEFAULTSECMSG
++#define GR_CHMOD_CHROOT_MSG "denied attempt to chmod +s %.950s by " DEFAULTSECMSG
++#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by " DEFAULTSECMSG
++#define GR_CHROOT_FCHDIR_MSG "attempted fchdir outside of chroot to %.950s by " DEFAULTSECMSG
++#define GR_CHOWN_ACL_MSG "%s chown of %.950s by " DEFAULTSECMSG
++#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by " DEFAULTSECMSG
++#define GR_INITF_ACL_MSG "init_variables() failed %s"
++#define GR_DISABLED_ACL_MSG "Error loading %s, trying to run kernel with acls disabled. To disable acls at startup use <kernel image name> gracl=off from your boot loader"
++#define GR_DEV_ACL_MSG "/dev/grsec: being fed garbage %d bytes sent %d required"
++#define GR_SHUTS_ACL_MSG "shutdown auth success for " DEFAULTSECMSG
++#define GR_SHUTF_ACL_MSG "shutdown auth failure for " DEFAULTSECMSG
++#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for " DEFAULTSECMSG
++#define GR_SEGVMODS_ACL_MSG "segvmod auth success for " DEFAULTSECMSG
++#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for " DEFAULTSECMSG
++#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for " DEFAULTSECMSG
++#define GR_ENABLE_ACL_MSG "Loaded %s"
++#define GR_ENABLEF_ACL_MSG "Unable to load %s for " DEFAULTSECMSG " RBAC system may already be enabled."
++#define GR_RELOADI_ACL_MSG "Ignoring reload request for disabled RBAC system"
++#define GR_RELOAD_ACL_MSG "Reloaded %s"
++#define GR_RELOADF_ACL_MSG "Failed reload of %s for " DEFAULTSECMSG
++#define GR_SPROLEI_ACL_MSG "Ignoring change to special role for disabled RBAC system for " DEFAULTSECMSG
++#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by " DEFAULTSECMSG
++#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by " DEFAULTSECMSG
++#define GR_SPROLEF_ACL_MSG "special role %s failure for " DEFAULTSECMSG
++#define GR_INVMODE_ACL_MSG "Invalid mode %d by " DEFAULTSECMSG
++#define GR_MAXPW_ACL_MSG "Maximum pw attempts reached (%d), locking password authentication"
++#define GR_MAXROLEPW_ACL_MSG "Maximum pw attempts reached (%d) trying to auth to special role %s, locking auth for role of " DEFAULTSECMSG
++#define GR_PRIORITY_CHROOT_MSG "attempted priority change of process (%.16s:%d) by " DEFAULTSECMSG
++#define GR_CAPSET_CHROOT_MSG "denied capset of (%.16s:%d) within chroot by " DEFAULTSECMSG
++#define GR_FAILFORK_MSG "failed fork with errno %d by " DEFAULTSECMSG
++#define GR_NICE_CHROOT_MSG "attempted priority change by " DEFAULTSECMSG
++#define GR_UNISIGLOG_MSG "signal %d sent to " DEFAULTSECMSG
++#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by " DEFAULTSECMSG
++#define GR_SIG_ACL_MSG "Attempted send of signal %d to protected task " DEFAULTSECMSG " by " DEFAULTSECMSG
++#define GR_SYSCTL_MSG "attempt to modify grsecurity sysctl value : %.32s by " DEFAULTSECMSG
++#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by " DEFAULTSECMSG
++#define GR_TIME_MSG "time set by " DEFAULTSECMSG
++#define GR_DEFACL_MSG "Fatal: Unable to find ACL for (%.16s:%d)"
++#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by " DEFAULTSECMSG
++#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by " DEFAULTSECMSG
++#define GR_SOCK_MSG "attempted socket(%.16s,%.16s,%.16s) by " DEFAULTSECMSG
++#define GR_BIND_MSG "attempted bind() by " DEFAULTSECMSG
++#define GR_CONNECT_MSG "attempted connect by " DEFAULTSECMSG
++#define GR_BIND_ACL_MSG "attempted bind to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by " DEFAULTSECMSG
++#define GR_CONNECT_ACL_MSG "attempted connect to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by " DEFAULTSECMSG
++#define GR_IP_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%u.%u.%u.%u\t%u\t%u\t%u\t%u\t%u.%u.%u.%u"
++#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process " DEFAULTSECMSG
++#define GR_CAP_ACL_MSG "use of %s denied for " DEFAULTSECMSG
++#define GR_REMOUNT_AUDIT_MSG "remount of %.30s by " DEFAULTSECMSG
++#define GR_UNMOUNT_AUDIT_MSG "unmount of %.30s by " DEFAULTSECMSG
++#define GR_MOUNT_AUDIT_MSG "mount %.30s to %.64s by " DEFAULTSECMSG
++#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by " DEFAULTSECMSG
++#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.63s) by " DEFAULTSECMSG
++#define GR_MSGQ_AUDIT_MSG "message queue created by " DEFAULTSECMSG
++#define GR_MSGQR_AUDIT_MSG "message queue of uid:%d euid:%d removed by " DEFAULTSECMSG
++#define GR_SEM_AUDIT_MSG "semaphore created by " DEFAULTSECMSG
++#define GR_SEMR_AUDIT_MSG "semaphore of uid:%d euid:%d removed by " DEFAULTSECMSG
++#define GR_SHM_AUDIT_MSG "shared memory of size %d created by " DEFAULTSECMSG
++#define GR_SHMR_AUDIT_MSG "shared memory of uid:%d euid:%d removed by " DEFAULTSECMSG
++#define GR_RESOURCE_MSG "attempted resource overstep by requesting %lu for %.16s against limit %lu by " DEFAULTSECMSG
+diff -urN linux-2.4.21/include/linux/grsecurity.h linux-2.4.21/include/linux/grsecurity.h
+--- linux-2.4.21/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/include/linux/grsecurity.h 2003-07-29 17:58:19.000000000 -0400
+@@ -0,0 +1,172 @@
++#ifndef GR_SECURITY_H
++#define GR_SECURITY_H
++
++extern int gr_pid_is_chrooted(const struct task_struct *p);
++extern int gr_handle_chroot_nice(void);
++extern int gr_handle_chroot_sysctl(const int op);
++extern int gr_handle_chroot_capset(const struct task_struct *target);
++extern int gr_handle_chroot_setpriority(const struct task_struct *p,
++ const int niceval);
++extern int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
++extern int gr_handle_chroot_chroot(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern void gr_handle_chroot_caps(struct task_struct *task);
++extern void gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt);
++extern int gr_handle_chroot_chmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode);
++extern int gr_handle_chroot_mknod(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int mode);
++extern int gr_handle_chroot_mount(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ const char *dev_name);
++extern int gr_handle_chroot_pivot(void);
++extern int gr_handle_chroot_unix(const pid_t pid);
++
++extern int gr_handle_nproc(void);
++
++extern void gr_handle_ioperm(void);
++extern void gr_handle_iopl(void);
++
++extern int gr_tpe_allow(const struct file *file);
++
++extern int gr_random_pid(spinlock_t * pid_lock);
++
++extern void gr_log_forkfail(const int retval);
++extern void gr_log_timechange(void);
++extern void gr_log_signal(const int sig, const struct task_struct *t);
++extern void gr_log_chdir(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern void gr_log_chroot_exec(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern void gr_handle_exec_args(struct linux_binprm *bprm, char **argv);
++extern void gr_log_remount(const char *devname, const int retval);
++extern void gr_log_unmount(const char *devname, const int retval);
++extern void gr_log_mount(const char *from, const char *to, const int retval);
++extern void gr_log_msgget(const int ret, const int msgflg);
++extern void gr_log_msgrm(const uid_t uid, const uid_t cuid);
++extern void gr_log_semget(const int err, const int semflg);
++extern void gr_log_semrm(const uid_t uid, const uid_t cuid);
++extern void gr_log_shmget(const int err, const int shmflg, const size_t size);
++extern void gr_log_shmrm(const uid_t uid, const uid_t cuid);
++
++extern int gr_handle_follow_link(const struct inode *parent,
++ const struct inode *inode,
++ const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern int gr_handle_fifo(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ const struct dentry *dir, const int flag,
++ const int acc_mode);
++extern int gr_handle_hardlink(const struct dentry *dentry,
++ const struct vfsmount *mnt,
++ struct inode *inode,
++ const int mode, const char *to);
++
++extern int gr_is_capable(const int cap);
++extern void gr_learn_resource(const struct task_struct *task, const int limit,
++ const unsigned long wanted);
++extern void gr_copy_label(struct task_struct *tsk);
++extern void gr_handle_crash(struct task_struct *task, const int sig);
++extern int gr_handle_signal(const struct task_struct *p, const int sig);
++extern int gr_check_crash_uid(const uid_t uid);
++extern int gr_check_protected_task(const struct task_struct *task);
++extern int gr_acl_handle_mmap(const struct file *file,
++ const unsigned long prot);
++extern int gr_acl_handle_mprotect(const struct file *file,
++ const unsigned long prot);
++extern int gr_check_hidden_task(const struct task_struct *tsk);
++extern __u32 gr_acl_handle_truncate(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern __u32 gr_acl_handle_utime(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern __u32 gr_acl_handle_access(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int fmode);
++extern __u32 gr_acl_handle_fchmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, mode_t mode);
++extern __u32 gr_acl_handle_chmod(const struct dentry *dentry,
++ const struct vfsmount *mnt, mode_t mode);
++extern __u32 gr_acl_handle_chown(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern int gr_handle_ptrace_exec(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern int gr_handle_ptrace(struct task_struct *task, const long request);
++extern int gr_handle_mmap(const struct file *filp, const unsigned long prot);
++extern __u32 gr_acl_handle_execve(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern int gr_check_crash_exec(const struct file *filp);
++extern int gr_acl_is_enabled(void);
++extern void gr_set_kernel_label(struct task_struct *task);
++extern void gr_set_role_label(struct task_struct *task, const uid_t uid,
++ const gid_t gid);
++extern void gr_set_proc_label(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern __u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern __u32 gr_acl_handle_open(const struct dentry *dentry,
++ const struct vfsmount *mnt, const int fmode);
++extern __u32 gr_acl_handle_creat(const struct dentry *dentry,
++ const struct dentry *p_dentry,
++ const struct vfsmount *p_mnt, const int fmode,
++ const int imode);
++extern void gr_handle_create(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern __u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const int mode);
++extern __u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt);
++extern __u32 gr_acl_handle_rmdir(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern void gr_handle_delete(const ino_t ino, const kdev_t dev);
++extern __u32 gr_acl_handle_unlink(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern __u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const char *from);
++extern __u32 gr_acl_handle_link(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const struct dentry *old_dentry,
++ const struct vfsmount *old_mnt, const char *to);
++extern int gr_acl_handle_rename(struct dentry *new_dentry,
++ struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ struct dentry *old_dentry,
++ struct inode *old_parent_inode,
++ struct vfsmount *old_mnt, const char *newname);
++extern __u32 gr_check_link(const struct dentry *new_dentry,
++ const struct dentry *parent_dentry,
++ const struct vfsmount *parent_mnt,
++ const struct dentry *old_dentry,
++ const struct vfsmount *old_mnt);
++extern __u32 gr_acl_handle_filldir(const struct dentry *dentry,
++ const struct vfsmount *mnt, const ino_t ino);
++extern __u32 gr_acl_handle_unix(const struct dentry *dentry,
++ const struct vfsmount *mnt);
++extern void gr_acl_handle_exit(void);
++extern void gr_acl_handle_psacct(struct task_struct *task, const long code);
++extern int gr_acl_handle_procpidmem(const struct task_struct *task);
++extern __u32 gr_cap_rtnetlink(void);
++
++#ifdef CONFIG_GRKERNSEC
++extern void gr_handle_mem_write(void);
++extern void gr_handle_kmem_write(void);
++extern void gr_handle_open_port(void);
++extern int gr_handle_mem_mmap(const unsigned long offset,
++ struct vm_area_struct *vma);
++
++extern __u16 ip_randomid(void);
++extern __u32 ip_randomisn(void);
++extern __u32 arc4random(void);
++
++extern int grsec_enable_dmesg;
++extern int grsec_enable_randid;
++extern int grsec_enable_randisn;
++extern int grsec_enable_randsrc;
++extern int grsec_enable_randrpc;
++#endif
++
++#endif
+diff -urN linux-2.4.21/include/linux/mm.h linux-2.4.21/include/linux/mm.h
+--- linux-2.4.21/include/linux/mm.h 2003-06-23 11:41:32.000000000 -0400
++++ linux-2.4.21/include/linux/mm.h 2003-06-23 11:49:17.000000000 -0400
+@@ -22,6 +22,9 @@
+ extern struct list_head active_list;
+ extern struct list_head inactive_list;
+
++extern void gr_learn_resource(const struct task_struct * task, const int limit,
++ const unsigned long wanted);
++
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+ #include <asm/atomic.h>
+@@ -639,6 +704,8 @@
+ address &= PAGE_MASK;
+ spin_lock(&vma->vm_mm->page_table_lock);
+ grow = (vma->vm_start - address) >> PAGE_SHIFT;
++ gr_learn_resource(current, RLIMIT_STACK, vma->vm_end - address);
++ gr_learn_resource(current, RLIMIT_AS, (vma->vm_mm->total_vm + grow) << PAGE_SHIFT);
+ if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
+ ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur) {
+ spin_unlock(&vma->vm_mm->page_table_lock);
+diff -urN linux-2.4.21/include/linux/proc_fs.h linux-2.4.21/include/linux/proc_fs.h
+--- linux-2.4.21/include/linux/proc_fs.h 2003-06-23 11:41:32.000000000 -0400
++++ linux-2.4.21/include/linux/proc_fs.h 2003-06-23 11:49:17.000000000 -0400
+@@ -143,6 +143,9 @@
+ extern struct proc_dir_entry *proc_mknod(const char *,mode_t,
+ struct proc_dir_entry *,kdev_t);
+ extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
++#ifdef CONFIG_GRKERNSEC_PROC
++extern struct proc_dir_entry *proc_priv_mkdir(const char *, struct proc_dir_entry *);
++#endif
+
+ static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+ mode_t mode, struct proc_dir_entry *base,
+diff -urN linux-2.4.21/include/linux/sched.h linux-2.4.21/include/linux/sched.h
+--- linux-2.4.21/include/linux/sched.h 2003-06-23 11:41:32.000000000 -0400
++++ linux-2.4.21/include/linux/sched.h 2003-06-23 11:49:17.000000000 -0400
+@@ -27,6 +27,9 @@
+ #include <linux/securebits.h>
+ #include <linux/fs_struct.h>
+
++extern int gr_is_capable(const int cap);
++extern int gr_pid_is_chrooted(const struct task_struct *p);
++
+ struct exec_domain;
+
+ /*
+@@ -415,6 +432,19 @@
+
+ /* journalling filesystem info */
+ void *journal_info;
++
++#ifdef CONFIG_GRKERNSEC
++/* added by grsecurity's ACL system */
++ struct acl_subject_label *acl;
++ struct acl_role_label *role;
++ struct file *exec_file;
++ u32 curr_ip;
++ u16 acl_role_id;
++ u8 acl_sp_role:1;
++ u8 used_accept:1;
++ u8 used_connect:1;
++ u8 is_writable:1;
++#endif
+ };
+
+ /*
+@@ -549,6 +586,8 @@
+ *p->pidhash_pprev = p->pidhash_next;
+ }
+
++#include <asm/current.h>
++
+ static inline task_t *find_task_by_pid(int pid)
+ {
+ task_t *p, **htable = &pidhash[pid_hashfn(pid)];
+@@ -556,6 +595,8 @@
+ for(p = *htable; p && p->pid != pid; p = p->pidhash_next)
+ ;
+
++ if(gr_pid_is_chrooted(p)) p = NULL;
++
+ return p;
+ }
+
+@@ -576,8 +617,6 @@
+ extern struct user_struct * alloc_uid(uid_t);
+ extern void free_uid(struct user_struct *);
+
+-#include <asm/current.h>
+-
+ extern unsigned long volatile jiffies;
+ extern unsigned long itimer_ticks;
+ extern unsigned long itimer_next;
+@@ -741,7 +780,7 @@
+ static inline int capable(int cap)
+ {
+ #if 1 /* ok now */
+- if (cap_raised(current->cap_effective, cap))
++ if (cap_raised(current->cap_effective, cap) && gr_is_capable(cap))
+ #else
+ if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
+ #endif
+diff -urN linux-2.4.21/include/linux/sysctl.h linux-2.4.21/include/linux/sysctl.h
+--- linux-2.4.21/include/linux/sysctl.h 2003-06-23 11:41:32.000000000 -0400
++++ linux-2.4.21/include/linux/sysctl.h 2003-06-23 11:49:17.000000000 -0400
+@@ -125,6 +125,7 @@
+ KERN_CADPID=54, /* int: PID of the process to notify on CAD */
+ KERN_KDB=55, /* int: kdb on/off */
+ KERN_CORE_PATTERN=56, /* string: pattern for core-files */
++ KERN_GRSECURITY=68, /* grsecurity */
+ };
+
+
+diff -urN linux-2.4.21/include/net/inetpeer.h linux-2.4.21/include/net/inetpeer.h
+--- linux-2.4.21/include/net/inetpeer.h 2003-06-23 11:41:37.000000000 -0400
++++ linux-2.4.21/include/net/inetpeer.h 2003-06-23 11:49:17.000000000 -0400
+@@ -13,6 +13,7 @@
+ #include <linux/init.h>
+ #include <linux/sched.h>
+ #include <linux/spinlock.h>
++
+ #include <asm/atomic.h>
+
+ struct inet_peer
+@@ -34,6 +35,11 @@
+ /* can be called with or without local BH being disabled */
+ struct inet_peer *inet_getpeer(__u32 daddr, int create);
+
++#ifdef CONFIG_GRKERNSEC_RANDID
++extern int grsec_enable_randid;
++extern __u16 ip_randomid(void);
++#endif
++
+ extern spinlock_t inet_peer_unused_lock;
+ extern struct inet_peer *inet_peer_unused_head;
+ extern struct inet_peer **inet_peer_unused_tailp;
+@@ -58,7 +64,14 @@
+ __u16 id;
+
+ spin_lock_bh(&inet_peer_idlock);
+- id = p->ip_id_count++;
++
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid)
++ id = htons(ip_randomid());
++ else
++#endif
++ id = p->ip_id_count++;
++
+ spin_unlock_bh(&inet_peer_idlock);
+ return id;
+ }
+diff -urN linux-2.4.21/include/net/ip.h linux-2.4.21/include/net/ip.h
+--- linux-2.4.21/include/net/ip.h 2003-06-23 11:41:37.000000000 -0400
++++ linux-2.4.21/include/net/ip.h 2003-06-23 11:49:17.000000000 -0400
+@@ -64,6 +64,11 @@
+ void (*destructor)(struct sock *);
+ };
+
++#ifdef CONFIG_GRKERNSEC_RANDID
++extern int grsec_enable_randid;
++extern __u16 ip_randomid(void);
++#endif
++
+ extern struct ip_ra_chain *ip_ra_chain;
+ extern rwlock_t ip_ra_lock;
+
+@@ -196,7 +201,13 @@
+ * does not change, they drop every other packet in
+ * a TCP stream using header compression.
+ */
+- iph->id = ((sk && sk->daddr) ? htons(sk->protinfo.af_inet.id++) : 0);
++
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid)
++ iph->id = htons(ip_randomid());
++ else
++#endif
++ iph->id = ((sk && sk->daddr) ? htons(sk->protinfo.af_inet.id++) : 0);
+ } else
+ __ip_select_ident(iph, dst);
+ }
+diff -urN linux-2.4.21/init/main.c linux-2.4.21/init/main.c
+--- linux-2.4.21/init/main.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/init/main.c 2003-06-23 11:49:17.000000000 -0400
+@@ -27,6 +27,7 @@
+ #include <linux/iobuf.h>
+ #include <linux/bootmem.h>
+ #include <linux/tty.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/io.h>
+ #include <asm/bugs.h>
+@@ -107,6 +108,8 @@
+ extern void ipc_init(void);
+ #endif
+
++extern void grsecurity_init(void);
++
+ /*
+ * Boot command-line arguments
+ */
+@@ -546,6 +549,7 @@
+ do_basic_setup();
+
+ prepare_namespace();
++ grsecurity_init();
+
+ /*
+ * Ok, we have completed the initial bootup, and
+diff -urN linux-2.4.21/ipc/msg.c linux-2.4.21/ipc/msg.c
+--- linux-2.4.21/ipc/msg.c 2003-06-23 11:41:59.000000000 -0400
++++ linux-2.4.21/ipc/msg.c 2003-06-23 11:49:17.000000000 -0400
+@@ -22,6 +22,7 @@
+ #include <linux/init.h>
+ #include <linux/proc_fs.h>
+ #include <linux/list.h>
++#include <linux/grsecurity.h>
+ #include <asm/uaccess.h>
+ #include "util.h"
+
+@@ -326,6 +327,9 @@
+ msg_unlock(id);
+ }
+ up(&msg_ids.sem);
++
++ gr_log_msgget(ret, msgflg);
++
+ return ret;
+ }
+
+@@ -560,6 +564,8 @@
+ break;
+ }
+ case IPC_RMID:
++ gr_log_msgrm(ipcp->uid, ipcp->cuid);
++
+ freeque (msqid);
+ break;
+ }
+diff -urN linux-2.4.21/ipc/sem.c linux-2.4.21/ipc/sem.c
+--- linux-2.4.21/ipc/sem.c 2003-06-23 11:41:59.000000000 -0400
++++ linux-2.4.21/ipc/sem.c 2003-06-23 11:49:17.000000000 -0400
+@@ -62,6 +62,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/init.h>
+ #include <linux/proc_fs.h>
++#include <linux/grsecurity.h>
+ #include <asm/uaccess.h>
+ #include "util.h"
+
+@@ -181,6 +182,9 @@
+ }
+
+ up(&sem_ids.sem);
++
++ gr_log_semget(err, semflg);
++
+ return err;
+ }
+
+@@ -728,6 +732,8 @@
+
+ switch(cmd){
+ case IPC_RMID:
++ gr_log_semrm(ipcp->uid, ipcp->cuid);
++
+ freeary(semid);
+ err = 0;
+ break;
+diff -urN linux-2.4.21/ipc/shm.c linux-2.4.21/ipc/shm.c
+--- linux-2.4.21/ipc/shm.c 2003-06-23 11:41:59.000000000 -0400
++++ linux-2.4.21/ipc/shm.c 2003-06-23 11:49:17.000000000 -0400
+@@ -23,6 +23,7 @@
+ #include <linux/mman.h>
+ #include <linux/proc_fs.h>
+ #include <asm/uaccess.h>
++#include <linux/grsecurity.h>
+
+ #include "util.h"
+
+@@ -38,8 +39,21 @@
+ time_t shm_ctim;
+ pid_t shm_cprid;
+ pid_t shm_lprid;
++
++#ifdef CONFIG_GRKERNSEC
++ time_t shm_createtime;
++ pid_t shm_lapid;
++#endif
+ };
+
++#ifdef CONFIG_GRKERNSEC
++extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime, const uid_t cuid,
++ const int shmid);
++extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
++ const time_t shm_createtime);
++#endif
++
+ #define shm_flags shm_perm.mode
+
+ static struct file_operations shm_file_operations;
+@@ -209,6 +223,9 @@
+ shp->shm_lprid = 0;
+ shp->shm_atim = shp->shm_dtim = 0;
+ shp->shm_ctim = CURRENT_TIME;
++#ifdef CONFIG_GRKERNSEC
++ shp->shm_createtime = CURRENT_TIME;
++#endif
+ shp->shm_segsz = size;
+ shp->shm_nattch = 0;
+ shp->id = shm_buildid(id,shp->shm_perm.seq);
+@@ -254,6 +271,9 @@
+ shm_unlock(id);
+ }
+ up(&shm_ids.sem);
++
++ gr_log_shmget(err, shmflg, size);
++
+ return err;
+ }
+
+@@ -509,6 +529,9 @@
+ err=-EPERM;
+ goto out_unlock_up;
+ }
++
++ gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid);
++
+ if (shp->shm_nattch){
+ shp->shm_flags |= SHM_DEST;
+ /* Do not find it any more */
+@@ -622,9 +645,28 @@
+ shm_unlock(shmid);
+ return -EACCES;
+ }
++
++#ifdef CONFIG_GRKERNSEC
++ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime,
++ shp->shm_perm.cuid, shmid)) {
++ shm_unlock(shmid);
++ return -EACCES;
++ }
++
++ if (!gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) {
++ shm_unlock(shmid);
++ return -EACCES;
++ }
++#endif
++
+ file = shp->shm_file;
+ size = file->f_dentry->d_inode->i_size;
+ shp->shm_nattch++;
++
++#ifdef CONFIG_GRKERNSEC
++ shp->shm_lapid = current->pid;
++#endif
++
+ shm_unlock(shmid);
+
+ down_write(¤t->mm->mmap_sem);
+diff -urN linux-2.4.21/kernel/capability.c linux-2.4.21/kernel/capability.c
+--- linux-2.4.21/kernel/capability.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/capability.c 2003-06-23 11:49:17.000000000 -0400
+@@ -7,6 +7,7 @@
+
+ #include <linux/mm.h>
+ #include <asm/uaccess.h>
++#include <linux/grsecurity.h>
+
+ kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
+
+@@ -168,6 +169,10 @@
+ target = current;
+ }
+
++ if (gr_handle_chroot_capset(target)) {
++ error = -ESRCH;
++ goto out;
++ }
+
+ /* verify restrictions on target's new Inheritable set */
+ if (!cap_issubset(inheritable,
+diff -urN linux-2.4.21/kernel/exit.c linux-2.4.21/kernel/exit.c
+--- linux-2.4.21/kernel/exit.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/exit.c 2003-06-23 11:49:17.000000000 -0400
+@@ -16,6 +16,7 @@
+ #ifdef CONFIG_BSD_PROCESS_ACCT
+ #include <linux/acct.h>
+ #endif
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+@@ -165,12 +165,21 @@
+ {
+ write_lock_irq(&tasklist_lock);
+
++#ifdef CONFIG_GRKERNSEC
++ if (current->exec_file) {
++ fput(current->exec_file);
++ current->exec_file = NULL;
++ }
++#endif
++
+ /* Reparent to init */
+ REMOVE_LINKS(current);
+ current->p_pptr = child_reaper;
+ current->p_opptr = child_reaper;
+ SET_LINKS(current);
+
++ gr_set_kernel_label(current);
++
+ /* Set the exit signal to SIGCHLD so we signal init on exit */
+ current->exit_signal = SIGCHLD;
+
+@@ -439,6 +440,10 @@
+ #ifdef CONFIG_BSD_PROCESS_ACCT
+ acct_process(code);
+ #endif
++
++ gr_acl_handle_psacct(tsk, code);
++ gr_acl_handle_exit();
++
+ __exit_mm(tsk);
+
+ lock_kernel();
+diff -urN linux-2.4.21/kernel/fork.c linux-2.4.21/kernel/fork.c
+--- linux-2.4.21/kernel/fork.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/fork.c 2003-06-23 11:49:17.000000000 -0400
+@@ -22,6 +22,7 @@
+ #include <linux/personality.h>
+ #include <linux/compiler.h>
+ #include <linux/mman.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/pgtable.h>
+ #include <asm/pgalloc.h>
+@@ -93,6 +94,10 @@
+ if (flags & CLONE_PID)
+ return current->pid;
+
++ pid = gr_random_pid(&lastpid_lock);
++ if (pid)
++ return pid;
++
+ spin_lock(&lastpid_lock);
+ beginpid = last_pid;
+ if((++last_pid) & 0xffff8000) {
+@@ -635,6 +640,9 @@
+ * friends to set the per-user process limit to something lower
+ * than the amount of processes root is running. -- Rik
+ */
++
++ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes));
++
+ if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur
+ && !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
+ goto bad_fork_free;
+@@ -719,6 +727,7 @@
+ retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
+ if (retval)
+ goto bad_fork_cleanup_namespace;
++ gr_copy_label(p);
+ p->semundo = NULL;
+
+ /* Our parent execution domain becomes current domain
+@@ -804,6 +813,9 @@
+ free_uid(p->user);
+ bad_fork_free:
+ free_task_struct(p);
++
++ gr_log_forkfail(retval);
++
+ goto fork_out;
+ }
+
+diff -urN linux-2.4.21/kernel/ksyms.c linux-2.4.21/kernel/ksyms.c
+--- linux-2.4.21/kernel/ksyms.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/ksyms.c 2003-06-23 11:49:17.000000000 -0400
+@@ -48,6 +48,7 @@
+ #include <linux/completion.h>
+ #include <linux/seq_file.h>
+ #include <linux/dnotify.h>
++#include <linux/grsecurity.h>
+ #include <asm/checksum.h>
+
+ #if defined(CONFIG_PROC_FS)
+@@ -585,3 +586,9 @@
+
+ /* debug */
+ EXPORT_SYMBOL(dump_stack);
++
++/* grsecurity */
++EXPORT_SYMBOL(gr_is_capable);
++EXPORT_SYMBOL(gr_pid_is_chrooted);
++EXPORT_SYMBOL(gr_learn_resource);
++EXPORT_SYMBOL(gr_set_kernel_label);
+diff -urN linux-2.4.21/kernel/module.c linux-2.4.21/kernel/module.c
+--- linux-2.4.21/kernel/module.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/module.c 2003-06-23 11:49:17.000000000 -0400
+@@ -887,6 +887,11 @@
+ struct module *mod;
+ int err;
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ if (!capable(CAP_SYS_MODULE))
++ return -EPERM;
++#endif
++
+ lock_kernel();
+ if (name_user == NULL)
+ mod = &kernel_module;
+@@ -956,6 +961,11 @@
+ int i;
+ struct kernel_sym ksym;
+
++#ifdef CONFIG_GRKERNSEC_HIDESYM
++ if (!capable(CAP_SYS_MODULE))
++ return 0;
++#endif
++
+ lock_kernel();
+ for (mod = module_list, i = 0; mod; mod = mod->next) {
+ /* include the count for the module name! */
+diff -urN linux-2.4.21/kernel/printk.c linux-2.4.21/kernel/printk.c
+--- linux-2.4.21/kernel/printk.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/printk.c 2003-06-23 11:49:17.000000000 -0400
+@@ -26,6 +26,7 @@
+ #include <linux/interrupt.h> /* For in_interrupt() */
+ #include <linux/config.h>
+ #include <linux/delay.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+
+@@ -294,6 +295,11 @@
+
+ asmlinkage long sys_syslog(int type, char * buf, int len)
+ {
++#ifdef CONFIG_GRKERNSEC_DMESG
++ if (!capable(CAP_SYS_ADMIN) && grsec_enable_dmesg)
++ return -EPERM;
++ else
++#endif
+ if ((type != 3) && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ return do_syslog(type, buf, len);
+diff -urN linux-2.4.21/kernel/sched.c linux-2.4.21/kernel/sched.c
+--- linux-2.4.21/kernel/sched.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/sched.c 2003-06-23 11:49:17.000000000 -0400
+@@ -29,11 +30,13 @@
+ #include <linux/nmi.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
++#include <linux/file.h>
+ #include <asm/uaccess.h>
+ #include <linux/smp_lock.h>
+ #include <asm/mmu_context.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/completion.h>
++#include <linux/grsecurity.h>
+
+ /*
+ * Convert user-nice values [ -20 ... 0 ... 19 ]
+@@ -910,6 +912,9 @@
+ return -EPERM;
+ if (increment < -40)
+ increment = -40;
++
++ if (gr_handle_chroot_nice())
++ return -EPERM;
+ }
+ if (increment > 40)
+ increment = 40;
+diff -urN linux-2.4.21/kernel/signal.c linux-2.4.21/kernel/signal.c
+--- linux-2.4.21/kernel/signal.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/signal.c 2003-06-23 11:49:17.000000000 -0400
+@@ -13,6 +13,8 @@
+ #include <linux/smp_lock.h>
+ #include <linux/init.h>
+ #include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+
+@@ -554,6 +556,8 @@
+ if (!sig || !t->sig)
+ goto out_nolock;
+
++ gr_log_signal(sig, t);
++
+ spin_lock_irqsave(&t->sigmask_lock, flags);
+ handle_stop_signal(sig, t);
+
+@@ -603,6 +607,8 @@
+ recalc_sigpending(t);
+ spin_unlock_irqrestore(&t->sigmask_lock, flags);
+
++ gr_handle_crash(t, sig);
++
+ return send_sig_info(sig, info, t);
+ }
+
+@@ -622,9 +628,13 @@
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pgrp == pgrp && thread_group_leader(p)) {
+- int err = send_sig_info(sig, info, p);
+- if (retval)
+- retval = err;
++ if (gr_handle_signal(p, sig))
++ retval = -EPERM;
++ else {
++ int err = send_sig_info(sig, info, p);
++ if (retval)
++ retval = err;
++ }
+ }
+ }
+ read_unlock(&tasklist_lock);
+@@ -675,7 +685,10 @@
+ if (tg)
+ p = tg;
+ }
+- error = send_sig_info(sig, info, p);
++ if (gr_handle_signal(p, sig))
++ error = -EPERM;
++ else
++ error = send_sig_info(sig, info, p);
+ }
+ read_unlock(&tasklist_lock);
+ return error;
+@@ -700,10 +713,14 @@
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (p->pid > 1 && p != current && thread_group_leader(p)) {
+- int err = send_sig_info(sig, info, p);
+- ++count;
+- if (err != -EPERM)
+- retval = err;
++ if (gr_handle_signal(p, sig))
++ retval = -EPERM;
++ else {
++ int err = send_sig_info(sig, info, p);
++ ++count;
++ if (err != -EPERM)
++ retval = err;
++ }
+ }
+ }
+ read_unlock(&tasklist_lock);
+diff -urN linux-2.4.21/kernel/sys.c linux-2.4.21/kernel/sys.c
+--- linux-2.4.21/kernel/sys.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/sys.c 2003-06-23 11:49:17.000000000 -0400
+@@ -4,6 +4,7 @@
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
++#include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/utsname.h>
+@@ -14,6 +15,7 @@
+ #include <linux/prctl.h>
+ #include <linux/init.h>
+ #include <linux/highuid.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -239,6 +241,12 @@
+ }
+ if (error == -ESRCH)
+ error = 0;
++
++ if (gr_handle_chroot_setpriority(p, niceval)) {
++ read_unlock(&tasklist_lock);
++ return -ESRCH;
++ }
++
+ if (niceval < task_nice(p) && !capable(CAP_SYS_NICE))
+ error = -EACCES;
+ else
+@@ -425,6 +433,9 @@
+ if (rgid != (gid_t) -1 ||
+ (egid != (gid_t) -1 && egid != old_rgid))
+ current->sgid = new_egid;
++
++ gr_set_role_label(current, current->uid, new_rgid);
++
+ current->fsgid = new_egid;
+ current->egid = new_egid;
+ current->gid = new_rgid;
+@@ -447,6 +458,9 @@
+ current->mm->dumpable=0;
+ wmb();
+ }
++
++ gr_set_role_label(current, current->uid, gid);
++
+ current->gid = current->egid = current->sgid = current->fsgid = gid;
+ }
+ else if ((gid == current->gid) || (gid == current->sgid))
+@@ -530,6 +544,9 @@
+ current->mm->dumpable = 0;
+ wmb();
+ }
++
++ gr_set_role_label(current, new_ruid, current->gid);
++
+ current->uid = new_ruid;
+ current->user = new_user;
+ free_uid(old_user);
+@@ -626,6 +643,9 @@
+ } else if ((uid != current->uid) && (uid != new_suid))
+ return -EPERM;
+
++ if (gr_check_crash_uid(uid))
++ return -EPERM;
++
+ if (old_euid != uid)
+ {
+ current->mm->dumpable = 0;
+@@ -722,8 +742,10 @@
+ current->egid = egid;
+ }
+ current->fsgid = current->egid;
+- if (rgid != (gid_t) -1)
++ if (rgid != (gid_t) -1) {
++ gr_set_role_label(current, current->uid, rgid);
+ current->gid = rgid;
++ }
+ if (sgid != (gid_t) -1)
+ current->sgid = sgid;
+ return 0;
+@@ -1140,6 +1162,10 @@
+ if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
+ return -EFAULT;
+ old_rlim = current->rlim + resource;
++
++ if (old_rlim->rlim_max < old_rlim->rlim_cur)
++ return -EINVAL;
++
+ if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
+ (new_rlim.rlim_max > old_rlim->rlim_max)) &&
+ !capable(CAP_SYS_RESOURCE))
+diff -urN linux-2.4.21/kernel/sysctl.c linux-2.4.21/kernel/sysctl.c
+--- linux-2.4.21/kernel/sysctl.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/sysctl.c 2003-06-23 11:49:17.000000000 -0400
+@@ -38,6 +38,13 @@
+ #endif
+
+ #if defined(CONFIG_SYSCTL)
++#include <linux/grsecurity.h>
++#include <linux/grinternal.h>
++
++extern __u32 gr_handle_sysctl(const ctl_table * table, const void *oldval,
++ const void *newval);
++extern int gr_handle_sysctl_mod(const char *dirname, const char *name, const int op);
++extern int gr_handle_chroot_sysctl(const int op);
+
+ /* External variables not in a header file. */
+ extern int panic_timeout;
+@@ -119,6 +126,8 @@
+ static ctl_table dev_table[];
+ extern ctl_table random_table[];
+
++static ctl_table grsecurity_table[];
++
+ /* /proc declarations: */
+
+ #ifdef CONFIG_PROC_FS
+@@ -259,8 +268,191 @@
+ {KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
+ &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
+ #endif
++#ifdef CONFIG_GRKERNSEC_SYSCTL
++ {KERN_GRSECURITY, "grsecurity", NULL, 0, 0555, grsecurity_table},
++#endif
++ {0}
++};
++
++#ifdef CONFIG_GRKERNSEC_SYSCTL
++enum {GS_LINK=1, GS_FIFO, GS_EXECVE, GS_EXECLOG, GS_SIGNAL,
++GS_FORKFAIL, GS_TIME, GS_CHROOT_SHMAT, GS_CHROOT_UNIX, GS_CHROOT_MNT,
++GS_CHROOT_FCHDIR, GS_CHROOT_DBL, GS_CHROOT_PVT, GS_CHROOT_CD, GS_CHROOT_CM,
++GS_CHROOT_MK, GS_CHROOT_NI, GS_CHROOT_EXECLOG, GS_CHROOT_CAPS,
++GS_CHROOT_SYSCTL, GS_TPE, GS_TPE_GID, GS_TPE_ALL, GS_SIDCAPS,
++GS_RANDPID, GS_RANDID, GS_RANDSRC, GS_RANDISN,
++GS_SOCKET_ALL, GS_SOCKET_ALL_GID, GS_SOCKET_CLIENT,
++GS_SOCKET_CLIENT_GID, GS_SOCKET_SERVER, GS_SOCKET_SERVER_GID, GS_TTY, GS_TTYS,
++GS_PTY, GS_GROUP, GS_GID, GS_ACHDIR, GS_AMOUNT, GS_AIPC, GS_DMSG, GS_RANDRPC,
++GS_FINDTASK, GS_LOCK};
++
++static ctl_table grsecurity_table[] = {
++#ifdef CONFIG_GRKERNSEC_LINK
++ {GS_LINK, "linking_restrictions", &grsec_enable_link, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_FIFO
++ {GS_FIFO, "fifo_restrictions", &grsec_enable_fifo, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECVE
++ {GS_EXECVE, "execve_limiting", &grsec_enable_execve, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_EXECLOG
++ {GS_EXECLOG, "exec_logging", &grsec_enable_execlog, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_SIGNAL
++ {GS_SIGNAL, "signal_logging", &grsec_enable_signal, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_FORKFAIL
++ {GS_FORKFAIL, "forkfail_logging", &grsec_enable_forkfail, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_TIME
++ {GS_TIME, "timechange_logging", &grsec_enable_time, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
++ {GS_CHROOT_SHMAT, "chroot_deny_shmat", &grsec_enable_chroot_shmat, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ {GS_CHROOT_UNIX, "chroot_deny_unix", &grsec_enable_chroot_unix, sizeof(int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
++ {GS_CHROOT_MNT, "chroot_deny_mount", &grsec_enable_chroot_mount, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
++ {GS_CHROOT_FCHDIR, "chroot_deny_fchdir", &grsec_enable_chroot_fchdir, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
++ {GS_CHROOT_DBL, "chroot_deny_chroot", &grsec_enable_chroot_double, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
++ {GS_CHROOT_PVT, "chroot_deny_pivot", &grsec_enable_chroot_pivot, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
++ {GS_CHROOT_CD, "chroot_enforce_chdir", &grsec_enable_chroot_chdir, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
++ {GS_CHROOT_CM, "chroot_deny_chmod", &grsec_enable_chroot_chmod, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
++ {GS_CHROOT_MK, "chroot_deny_mknod", &grsec_enable_chroot_mknod, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
++ {GS_CHROOT_NI, "chroot_restrict_nice", &grsec_enable_chroot_nice, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
++ {GS_CHROOT_EXECLOG, "chroot_execlog",
++ &grsec_enable_chroot_execlog, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
++ {GS_CHROOT_CAPS, "chroot_caps", &grsec_enable_chroot_caps, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
++ {GS_CHROOT_SYSCTL, "chroot_deny_sysctl", &grsec_enable_chroot_sysctl, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE
++ {GS_TPE, "tpe", &grsec_enable_tpe, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++ {GS_TPE_GID, "tpe_gid", &grsec_tpe_gid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_TPE_ALL
++ {GS_TPE_ALL, "tpe_restrict_all", &grsec_enable_tpe_all, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDPID
++ {GS_RANDPID, "rand_pids", &grsec_enable_randpid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDID
++ {GS_RANDID, "rand_ip_ids", &grsec_enable_randid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDSRC
++ {GS_RANDSRC, "rand_tcp_src_ports", &grsec_enable_randsrc, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDISN
++ {GS_RANDISN, "rand_isns", &grsec_enable_randisn, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
++ {GS_SOCKET_ALL, "socket_all", &grsec_enable_socket_all, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++ {GS_SOCKET_ALL_GID, "socket_all_gid",
++ &grsec_socket_all_gid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
++ {GS_SOCKET_CLIENT, "socket_client",
++ &grsec_enable_socket_client, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++ {GS_SOCKET_CLIENT_GID, "socket_client_gid",
++ &grsec_socket_client_gid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
++ {GS_SOCKET_SERVER, "socket_server",
++ &grsec_enable_socket_server, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++ {GS_SOCKET_SERVER_GID, "socket_server_gid",
++ &grsec_socket_server_gid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
++ {GS_GROUP, "audit_group", &grsec_enable_group, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++ {GS_GID, "audit_gid",
++ &grsec_audit_gid, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
++ {GS_ACHDIR, "audit_chdir", &grsec_enable_chdir, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
++ {GS_AMOUNT, "audit_mount", &grsec_enable_mount, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
++ {GS_AIPC, "audit_ipc", &grsec_enable_audit_ipc, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_DMESG
++ {GS_AIPC, "dmesg", &grsec_enable_dmesg, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDRPC
++ {GS_RANDRPC, "rand_rpc", &grsec_enable_randrpc, sizeof (int),
++ 0600, NULL, &proc_dointvec},
++#endif
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
++ {GS_FINDTASK, "chroot_findtask", &grsec_enable_chroot_findtask,
++ sizeof (int), 0600, NULL, &proc_dointvec},
++#endif
++ {GS_LOCK, "grsec_lock", &grsec_lock, sizeof (int), 0600, NULL,
++ &proc_dointvec},
+ {0}
+ };
++#endif
+
+ static ctl_table vm_table[] = {
+ {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
+@@ -395,6 +587,11 @@
+
+ static inline int ctl_perm(ctl_table *table, int op)
+ {
++ if (gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op))
++ return -EACCES;
++ if (gr_handle_chroot_sysctl(op))
++ return -EACCES;
++
+ return test_perm(table->mode, op);
+ }
+
+@@ -428,6 +625,10 @@
+ table = table->child;
+ goto repeat;
+ }
++
++ if (!gr_handle_sysctl(table, oldval, newval))
++ return -EACCES;
++
+ error = do_sysctl_strategy(table, name, nlen,
+ oldval, oldlenp,
+ newval, newlen, context);
+diff -urN linux-2.4.21/kernel/time.c linux-2.4.21/kernel/time.c
+--- linux-2.4.21/kernel/time.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/time.c 2003-06-23 11:49:17.000000000 -0400
+@@ -27,6 +27,7 @@
+ #include <linux/mm.h>
+ #include <linux/timex.h>
+ #include <linux/smp_lock.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+
+@@ -89,6 +90,9 @@
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+ write_unlock_irq(&xtime_lock);
++
++ gr_log_timechange();
++
+ return 0;
+ }
+
+@@ -167,6 +171,8 @@
+ * globally block out interrupts when it runs.
+ */
+ do_settimeofday(tv);
++
++ gr_log_timechange();
+ }
+ return 0;
+ }
+diff -urN linux-2.4.21/kernel/timer.c linux-2.4.21/kernel/timer.c
+--- linux-2.4.21/kernel/timer.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/kernel/timer.c 2003-06-23 11:49:17.000000000 -0400
+@@ -541,6 +541,9 @@
+
+ psecs = (p->times.tms_utime += user);
+ psecs += (p->times.tms_stime += system);
++
++ gr_learn_resource(p, RLIMIT_CPU, psecs / HZ);
++
+ if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur) {
+ /* Send SIGXCPU every second.. */
+ if (!(psecs % HZ))
+diff -urN linux-2.4.21/mm/filemap.c linux-2.4.21/mm/filemap.c
+--- linux-2.4.21/mm/filemap.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/filemap.c 2003-06-23 11:49:17.000000000 -0400
+@@ -2501,6 +2507,7 @@
+ error = -EIO;
+ rlim_rss = current->rlim ? current->rlim[RLIMIT_RSS].rlim_cur :
+ LONG_MAX; /* default: see resource.h */
++ gr_learn_resource(current, RLIMIT_RSS, vma->vm_mm->rss + (end - start));
+ if ((vma->vm_mm->rss + (end - start)) > rlim_rss)
+ return error;
+
+@@ -3004,6 +3011,7 @@
+ err = -EFBIG;
+
+ if (!S_ISBLK(inode->i_mode) && limit != RLIM_INFINITY) {
++ gr_learn_resource(current, RLIMIT_FSIZE, pos);
+ if (pos >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+@@ -3039,6 +3047,7 @@
+ */
+
+ if (!S_ISBLK(inode->i_mode)) {
++ gr_learn_resource(current, RLIMIT_FSIZE, count + (u32)pos);
+ if (pos >= inode->i_sb->s_maxbytes)
+ {
+ if (count || pos > inode->i_sb->s_maxbytes) {
+diff -urN linux-2.4.21/mm/memory.c linux-2.4.21/mm/memory.c
+--- linux-2.4.21/mm/memory.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/memory.c 2003-06-23 11:49:17.000000000 -0400
+@@ -1065,6 +1129,7 @@
+
+ do_expand:
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
++ gr_learn_resource(current, RLIMIT_FSIZE, offset);
+ if (limit != RLIM_INFINITY && offset > limit)
+ goto out_sig;
+ if (offset > inode->i_sb->s_maxbytes)
+diff -urN linux-2.4.21/mm/mlock.c linux-2.4.21/mm/mlock.c
+--- linux-2.4.21/mm/mlock.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/mlock.c 2003-06-23 11:49:17.000000000 -0400
+@@ -209,6 +235,7 @@
+ lock_limit >>= PAGE_SHIFT;
+
+ /* check against resource limits */
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked);
+ if (locked > lock_limit)
+ goto out;
+
+@@ -276,6 +303,7 @@
+ lock_limit >>= PAGE_SHIFT;
+
+ ret = -ENOMEM;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm);
+ if (current->mm->total_vm > lock_limit)
+ goto out;
+
+diff -urN linux-2.4.21/mm/mmap.c linux-2.4.21/mm/mmap.c
+--- linux-2.4.21/mm/mmap.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/mmap.c 2003-06-23 11:49:17.000000000 -0400
+@@ -14,6 +14,8 @@
+ #include <linux/file.h>
+ #include <linux/fs.h>
+ #include <linux/personality.h>
++#include <linux/random.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+@@ -168,6 +170,7 @@
+
+ /* Check against rlimit.. */
+ rlim = current->rlim[RLIMIT_DATA].rlim_cur;
++ gr_learn_resource(current, RLIMIT_DATA, brk - mm->start_data);
+ if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
+ goto out;
+
+@@ -432,6 +462,7 @@
+ if (vm_flags & VM_LOCKED) {
+ unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+ locked += len;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked);
+ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ return -EAGAIN;
+ }
+@@ -480,6 +532,9 @@
+ }
+ }
+
++ if (!gr_acl_handle_mmap(file, prot))
++ return -EACCES;
++
+ /* Clear old maps */
+ munmap_back:
+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
+@@ -490,6 +545,7 @@
+ }
+
+ /* Check against address space limit. */
++ gr_learn_resource(current, RLIMIT_AS, (mm->total_vm << PAGE_SHIFT) + len);
+ if ((mm->total_vm << PAGE_SHIFT) + len
+ > current->rlim[RLIMIT_AS].rlim_cur)
+ return -ENOMEM;
+@@ -1047,6 +1255,7 @@
+ if (mm->def_flags & VM_LOCKED) {
+ unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+ locked += len;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked);
+ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ return -EAGAIN;
+ }
+@@ -1063,6 +1272,7 @@
+ }
+
+ /* Check against address space limits *after* clearing old maps... */
++ gr_learn_resource(current, RLIMIT_AS, (mm->total_vm << PAGE_SHIFT) + len);
+ if ((mm->total_vm << PAGE_SHIFT) + len
+ > current->rlim[RLIMIT_AS].rlim_cur)
+ return -ENOMEM;
+diff -urN linux-2.4.21/mm/mprotect.c linux-2.4.21/mm/mprotect.c
+--- linux-2.4.21/mm/mprotect.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/mprotect.c 2003-06-23 11:49:17.000000000 -0400
+@@ -7,6 +7,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/shm.h>
+ #include <linux/mman.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+@@ -288,6 +392,11 @@
+ if (!vma || vma->vm_start > start)
+ goto out;
+
++ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) {
++ error = -EACCES;
++ goto out;
++ }
++
+ for (nstart = start ; ; ) {
+ unsigned int newflags;
+ int last = 0;
+diff -urN linux-2.4.21/mm/mremap.c linux-2.4.21/mm/mremap.c
+--- linux-2.4.21/mm/mremap.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/mremap.c 2003-06-23 11:49:17.000000000 -0400
+@@ -278,10 +301,13 @@
+ unsigned long locked = current->mm->locked_vm << PAGE_SHIFT;
+ locked += new_len - old_len;
+ ret = -EAGAIN;
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked);
+ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ goto out;
+ }
+ ret = -ENOMEM;
++
++ gr_learn_resource(current, RLIMIT_AS, (current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len));
+ if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
+ > current->rlim[RLIMIT_AS].rlim_cur)
+ goto out;
+diff -urN linux-2.4.21/mm/shmem.c linux-2.4.21/mm/shmem.c
+--- linux-2.4.21/mm/shmem.c 2003-06-23 11:41:31.000000000 -0400
++++ linux-2.4.21/mm/shmem.c 2003-06-23 11:49:17.000000000 -0400
+@@ -822,6 +822,8 @@
+ */
+ err = -EFBIG;
+ if (limit != RLIM_INFINITY) {
++ gr_learn_resource(current, RLIMIT_FSIZE, pos);
++
+ if (pos >= limit) {
+ send_sig(SIGXFSZ, current, 0);
+ goto out;
+diff -urN linux-2.4.21/net/ipv4/af_inet.c linux-2.4.21/net/ipv4/af_inet.c
+--- linux-2.4.21/net/ipv4/af_inet.c 2003-06-23 11:41:55.000000000 -0400
++++ linux-2.4.21/net/ipv4/af_inet.c 2003-06-23 11:49:17.000000000 -0400
+@@ -83,6 +83,7 @@
+ #include <linux/init.h>
+ #include <linux/poll.h>
+ #include <linux/netfilter_ipv4.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -374,7 +375,12 @@
+ else
+ sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_WANT;
+
+- sk->protinfo.af_inet.id = 0;
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid)
++ sk->protinfo.af_inet.id = htons(ip_randomid());
++ else
++#endif
++ sk->protinfo.af_inet.id = 0;
+
+ sock_init_data(sock,sk);
+
+diff -urN linux-2.4.21/net/ipv4/icmp.c linux-2.4.21/net/ipv4/icmp.c
+--- linux-2.4.21/net/ipv4/icmp.c 2003-06-23 11:41:55.000000000 -0400
++++ linux-2.4.21/net/ipv4/icmp.c 2003-06-23 11:49:17.000000000 -0400
+@@ -87,6 +87,8 @@
+ #include <linux/errno.h>
+ #include <linux/timer.h>
+ #include <linux/init.h>
++#include <linux/grsecurity.h>
++
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <net/checksum.h>
+@@ -712,6 +714,7 @@
+
+ icmp_param.data.icmph=*skb->h.icmph;
+ icmp_param.data.icmph.type=ICMP_ECHOREPLY;
++
+ icmp_param.skb=skb;
+ icmp_param.offset=0;
+ icmp_param.data_len=skb->len;
+diff -urN linux-2.4.21/net/ipv4/ip_output.c linux-2.4.21/net/ipv4/ip_output.c
+--- linux-2.4.21/net/ipv4/ip_output.c 2003-07-29 17:57:12.000000000 -0400
++++ linux-2.4.21/net/ipv4/ip_output.c 2003-07-29 17:58:20.000000000 -0400
+@@ -77,6 +77,7 @@
+ #include <linux/netfilter_ipv4.h>
+ #include <linux/mroute.h>
+ #include <linux/netlink.h>
++#include <linux/grsecurity.h>
+
+ /*
+ * Shall we try to damage output packets if routing dev changes?
+@@ -511,7 +512,13 @@
+ * Begin outputting the bytes.
+ */
+
+- id = sk->protinfo.af_inet.id++;
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid) {
++ id = htons(ip_randomid());
++ sk->protinfo.af_inet.id = htons(ip_randomid());
++ } else
++#endif
++ id = sk->protinfo.af_inet.id++;
+
+ do {
+ char *data;
+diff -urN linux-2.4.21/net/ipv4/netfilter/Config.in linux-2.4.21/net/ipv4/netfilter/Config.in
+--- linux-2.4.21/net/ipv4/netfilter/Config.in 2003-06-23 11:41:55.000000000 -0400
++++ linux-2.4.21/net/ipv4/netfilter/Config.in 2003-06-23 11:49:17.000000000 -0400
+@@ -32,6 +32,7 @@
+ dep_tristate ' address type match support' CONFIG_IP_NF_MATCH_ADDRTYPE $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' tcpmss match support' CONFIG_IP_NF_MATCH_TCPMSS $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' realm match support' CONFIG_IP_NF_MATCH_REALM $CONFIG_IP_NF_IPTABLES
++ dep_tristate ' stealth match support' CONFIG_IP_NF_MATCH_STEALTH $CONFIG_IP_NF_IPTABLES
+ if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
+ dep_tristate ' Helper match support' CONFIG_IP_NF_MATCH_HELPER $CONFIG_IP_NF_IPTABLES
+ fi
+diff -urN linux-2.4.21/net/ipv4/netfilter/Makefile linux-2.4.21/net/ipv4/netfilter/Makefile
+--- linux-2.4.21/net/ipv4/netfilter/Makefile 2003-06-23 11:41:55.000000000 -0400
++++ linux-2.4.21/net/ipv4/netfilter/Makefile 2003-06-23 11:49:17.000000000 -0400
+@@ -83,6 +83,7 @@
+ obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
+ obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
+ obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
++obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
+ obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
+ obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
+
+diff -urN linux-2.4.21/net/ipv4/netfilter/ipt_stealth.c linux-2.4.21/net/ipv4/netfilter/ipt_stealth.c
+--- linux-2.4.21/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.4.21/net/ipv4/netfilter/ipt_stealth.c 2003-06-23 11:49:17.000000000 -0400
+@@ -0,0 +1,109 @@
++/* Kernel module to add stealth support.
++ *
++ * Copyright (C) 2002 Brad Spengler <spender@grsecurity.net>
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/net.h>
++#include <linux/sched.h>
++#include <linux/inet.h>
++#include <linux/stddef.h>
++
++#include <net/ip.h>
++#include <net/sock.h>
++#include <net/tcp.h>
++#include <net/udp.h>
++#include <net/route.h>
++#include <net/inet_common.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++MODULE_LICENSE("GPL");
++
++extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
++
++static int
++match(const struct sk_buff *skb,
++ const struct net_device *in,
++ const struct net_device *out,
++ const void *matchinfo,
++ int offset,
++ const void *hdr,
++ u_int16_t datalen,
++ int *hotdrop)
++{
++ struct iphdr *ip = skb->nh.iph;
++ struct tcphdr *th = (struct tcphdr *) hdr;
++ struct udphdr *uh = (struct udphdr *) hdr;
++ struct sock *sk = NULL;
++
++ if (!ip || !hdr || offset) return 0;
++
++ switch(ip->protocol) {
++ case IPPROTO_TCP:
++ if (datalen < sizeof(struct tcphdr)) {
++ *hotdrop = 1;
++ return 0;
++ }
++ if (!(th->syn && !th->ack)) return 0;
++ sk = tcp_v4_lookup_listener(ip->daddr, ntohs(th->dest), ((struct rtable*)skb->dst)->rt_iif);
++ break;
++ case IPPROTO_UDP:
++ if (datalen < sizeof(struct udphdr)) {
++ *hotdrop = 1;
++ return 0;
++ }
++ sk = udp_v4_lookup(ip->saddr, uh->source, ip->daddr, uh->dest, skb->dev->ifindex);
++ break;
++ default:
++ return 0;
++ }
++
++ if(!sk) // port is being listened on, match this
++ return 1;
++ else {
++ sock_put(sk);
++ return 0;
++ }
++}
++
++/* Called when user tries to insert an entry of this type. */
++static int
++checkentry(const char *tablename,
++ const struct ipt_ip *ip,
++ void *matchinfo,
++ unsigned int matchsize,
++ unsigned int hook_mask)
++{
++ if (matchsize != IPT_ALIGN(0))
++ return 0;
++
++ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) ||
++ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO)))
++ && (hook_mask & (1 << NF_IP_LOCAL_IN)))
++ return 1;
++
++ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n");
++
++ return 0;
++}
++
++
++static struct ipt_match stealth_match
++= { { NULL, NULL }, "stealth", &match, &checkentry, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++ return ipt_register_match(&stealth_match);
++}
++
++static void __exit fini(void)
++{
++ ipt_unregister_match(&stealth_match);
++}
++
++module_init(init);
++module_exit(fini);
+diff -urN linux-2.4.21/net/ipv4/tcp_ipv4.c linux-2.4.21/net/ipv4/tcp_ipv4.c
+--- linux-2.4.21/net/ipv4/tcp_ipv4.c 2003-06-23 11:41:55.000000000 -0400
++++ linux-2.4.21/net/ipv4/tcp_ipv4.c 2003-06-23 11:49:17.000000000 -0400
+@@ -67,6 +67,7 @@
+ #include <linux/inet.h>
+ #include <linux/stddef.h>
+ #include <linux/ipsec.h>
++#include <linux/grsecurity.h>
+
+ extern int sysctl_ip_dynaddr;
+ extern int sysctl_ip_default_ttl;
+@@ -221,9 +222,18 @@
+
+ spin_lock(&tcp_portalloc_lock);
+ rover = tcp_port_rover;
+- do { rover++;
+- if ((rover < low) || (rover > high))
+- rover = low;
++ do {
++#ifdef CONFIG_GRKERNSEC_RANDSRC
++ if (grsec_enable_randsrc && (high > low)) {
++ rover = low + (arc4random() % (high - low));
++ } else
++#endif
++ {
++ rover++;
++ if ((rover < low) || (rover > high))
++ rover = low;
++ }
++
+ head = &tcp_bhash[tcp_bhashfn(rover)];
+ spin_lock(&head->lock);
+ for (tb = head->chain; tb; tb = tb->next)
+@@ -546,6 +556,11 @@
+
+ static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+ {
++#ifdef CONFIG_GRKERNSEC_RANDISN
++ if (likely(grsec_enable_randisn))
++ return ip_randomisn();
++ else
++#endif
+ return secure_tcp_sequence_number(skb->nh.iph->daddr,
+ skb->nh.iph->saddr,
+ skb->h.th->dest,
+@@ -681,9 +696,16 @@
+ rover = tcp_port_rover;
+
+ do {
+- rover++;
+- if ((rover < low) || (rover > high))
+- rover = low;
++#ifdef CONFIG_GRKERNSEC_RANDSRC
++ if(grsec_enable_randsrc && (high > low)) {
++ rover = low + (arc4random() % (high - low));
++ } else
++#endif
++ {
++ rover++;
++ if ((rover < low) || (rover > high))
++ rover = low;
++ }
+ head = &tcp_bhash[tcp_bhashfn(rover)];
+ spin_lock(&head->lock);
+
+@@ -844,11 +866,22 @@
+ if (err)
+ goto failure;
+
+- if (!tp->write_seq)
++ if (!tp->write_seq) {
++#ifdef CONFIG_GRKERNSEC_RANDISN
++ if (likely(grsec_enable_randisn))
++ tp->write_seq = ip_randomisn();
++ else
++#endif
+ tp->write_seq = secure_tcp_sequence_number(sk->saddr, sk->daddr,
+ sk->sport, usin->sin_port);
++ }
+
+- sk->protinfo.af_inet.id = tp->write_seq^jiffies;
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid)
++ sk->protinfo.af_inet.id = htons(ip_randomid());
++ else
++#endif
++ sk->protinfo.af_inet.id = tp->write_seq^jiffies;
+
+ err = tcp_connect(sk);
+ if (err)
+@@ -1570,7 +1603,13 @@
+ newtp->ext_header_len = 0;
+ if (newsk->protinfo.af_inet.opt)
+ newtp->ext_header_len = newsk->protinfo.af_inet.opt->optlen;
+- newsk->protinfo.af_inet.id = newtp->write_seq^jiffies;
++
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid)
++ newsk->protinfo.af_inet.id = htons(ip_randomid());
++ else
++#endif
++ newsk->protinfo.af_inet.id = newtp->write_seq^jiffies;
+
+ tcp_sync_mss(newsk, dst->pmtu);
+ newtp->advmss = dst->advmss;
+diff -urN linux-2.4.21/net/ipv4/udp.c linux-2.4.21/net/ipv4/udp.c
+--- linux-2.4.21/net/ipv4/udp.c 2003-06-23 11:41:55.000000000 -0400
++++ linux-2.4.21/net/ipv4/udp.c 2003-06-23 11:49:17.000000000 -0400
+@@ -91,6 +91,7 @@
+ #include <net/ipv6.h>
+ #include <net/protocol.h>
+ #include <linux/skbuff.h>
++#include <linux/grsecurity.h>
+ #include <net/sock.h>
+ #include <net/udp.h>
+ #include <net/icmp.h>
+@@ -98,6 +99,11 @@
+ #include <net/inet_common.h>
+ #include <net/checksum.h>
+
++extern int gr_search_udp_recvmsg(const struct sock *sk,
++ const struct sk_buff *skb);
++extern int gr_search_udp_sendmsg(const struct sock *sk,
++ const struct sockaddr_in *addr);
++
+ /*
+ * Snmp MIB for the UDP layer
+ */
+@@ -474,9 +480,16 @@
+ ufh.uh.dest = usin->sin_port;
+ if (ufh.uh.dest == 0)
+ return -EINVAL;
++
++ if (!gr_search_udp_sendmsg(sk, usin))
++ return -EPERM;
+ } else {
+ if (sk->state != TCP_ESTABLISHED)
+ return -ENOTCONN;
++
++ if (!gr_search_udp_sendmsg(sk, NULL))
++ return -EPERM;
++
+ ufh.daddr = sk->daddr;
+ ufh.uh.dest = sk->dport;
+ /* Open fast path for connected socket.
+@@ -484,6 +497,7 @@
+ */
+ connected = 1;
+ }
++
+ ipc.addr = sk->saddr;
+ ufh.uh.source = sk->sport;
+
+@@ -655,6 +669,11 @@
+ if (!skb)
+ goto out;
+
++ if (!gr_search_udp_recvmsg(sk, skb)) {
++ err = -EPERM;
++ goto out_free;
++ }
++
+ copied = skb->len - sizeof(struct udphdr);
+ if (copied > len) {
+ copied = len;
+@@ -759,7 +778,13 @@
+ sk->daddr = rt->rt_dst;
+ sk->dport = usin->sin_port;
+ sk->state = TCP_ESTABLISHED;
+- sk->protinfo.af_inet.id = jiffies;
++
++#ifdef CONFIG_GRKERNSEC_RANDID
++ if(grsec_enable_randid)
++ sk->protinfo.af_inet.id = htons(ip_randomid());
++ else
++#endif
++ sk->protinfo.af_inet.id = jiffies;
+
+ sk_dst_set(sk, &rt->u.dst);
+ return(0);
+diff -urN linux-2.4.21/net/netlink/af_netlink.c linux-2.4.21/net/netlink/af_netlink.c
+--- linux-2.4.21/net/netlink/af_netlink.c 2003-06-23 11:41:58.000000000 -0400
++++ linux-2.4.21/net/netlink/af_netlink.c 2003-06-23 11:49:17.000000000 -0400
+@@ -40,6 +40,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/smp_lock.h>
+ #include <linux/notifier.h>
++#include <linux/grsecurity.h>
+ #include <net/sock.h>
+ #include <net/scm.h>
+
+@@ -620,7 +621,8 @@
+ check them, when this message will be delivered
+ to corresponding kernel module. --ANK (980802)
+ */
+- NETLINK_CB(skb).eff_cap = current->cap_effective;
++
++ NETLINK_CB(skb).eff_cap = gr_cap_rtnetlink();
+
+ err = -EFAULT;
+ if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
+diff -urN linux-2.4.21/net/netsyms.c linux-2.4.21/net/netsyms.c
+--- linux-2.4.21/net/netsyms.c 2003-06-23 11:41:53.000000000 -0400
++++ linux-2.4.21/net/netsyms.c 2003-06-23 11:49:17.000000000 -0400
+@@ -24,6 +24,7 @@
+ #include <net/checksum.h>
+ #include <linux/etherdevice.h>
+ #include <net/route.h>
++#include <linux/grsecurity.h>
+ #ifdef CONFIG_HIPPI
+ #include <linux/hippidevice.h>
+ #endif
+@@ -598,6 +599,47 @@
+
+ EXPORT_SYMBOL(softnet_data);
+
++#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
++#if !defined (CONFIG_IPV6_MODULE) && !defined (CONFIG_KHTTPD) && !defined (CONFIG_KHTTPD_MODULE)
++EXPORT_SYMBOL(tcp_v4_lookup_listener);
++#endif
++#endif
++
++#if defined(CONFIG_GRKERNSEC_RANDID)
++EXPORT_SYMBOL(ip_randomid);
++#endif
++#if defined(CONFIG_GRKERNSEC_RANDSRC) || defined(CONFIG_GRKERNSEC_RANDRPC)
++EXPORT_SYMBOL(arc4random);
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDISN
++EXPORT_SYMBOL(ip_randomisn);
++EXPORT_SYMBOL(grsec_enable_randisn);
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDID
++EXPORT_SYMBOL(grsec_enable_randid);
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDSRC
++EXPORT_SYMBOL(grsec_enable_randsrc);
++#endif
++#ifdef CONFIG_GRKERNSEC_RANDRPC
++EXPORT_SYMBOL(grsec_enable_randrpc);
++#endif
++
++EXPORT_SYMBOL(gr_cap_rtnetlink);
++
++extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb);
++extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr);
++
++EXPORT_SYMBOL(gr_search_udp_recvmsg);
++EXPORT_SYMBOL(gr_search_udp_sendmsg);
++
++#ifdef CONFIG_UNIX_MODULE
++EXPORT_SYMBOL(gr_acl_handle_unix);
++EXPORT_SYMBOL(gr_acl_handle_mknod);
++EXPORT_SYMBOL(gr_handle_chroot_unix);
++EXPORT_SYMBOL(gr_handle_create);
++#endif
++
+ #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
+ #include <net/iw_handler.h>
+ EXPORT_SYMBOL(wireless_send_event);
+diff -urN linux-2.4.21/net/socket.c linux-2.4.21/net/socket.c
+--- linux-2.4.21/net/socket.c 2003-06-23 11:41:53.000000000 -0400
++++ linux-2.4.21/net/socket.c 2003-06-23 11:49:17.000000000 -0400
+@@ -85,6 +85,18 @@
+ #include <net/scm.h>
+ #include <linux/netfilter.h>
+
++extern void gr_attach_curr_ip(const struct sock *sk);
++extern int gr_handle_sock_all(const int family, const int type,
++ const int protocol);
++extern int gr_handle_sock_server(const struct sockaddr *sck);
++extern int gr_handle_sock_client(const struct sockaddr *sck);
++extern int gr_search_connect(const struct socket * sock,
++ const struct sockaddr_in * addr);
++extern int gr_search_bind(const struct socket * sock,
++ const struct sockaddr_in * addr);
++extern int gr_search_socket(const int domain, const int type,
++ const int protocol);
++
+ static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
+ static ssize_t sock_read(struct file *file, char *buf,
+ size_t size, loff_t *ppos);
+@@ -699,6 +711,7 @@
+
+ int sock_close(struct inode *inode, struct file *filp)
+ {
++ struct socket *sock;
+ /*
+ * It was possible the inode is NULL we were
+ * closing an unfinished socket.
+@@ -709,8 +722,21 @@
+ printk(KERN_DEBUG "sock_close: NULL inode\n");
+ return 0;
+ }
++ sock = socki_lookup(inode);
++
+ sock_fasync(-1, filp, 0);
++
++#ifdef CONFIG_GRKERNSEC
++ if (unlikely(current->used_accept && sock->sk &&
++ (sock->sk->protocol == IPPROTO_TCP) &&
++ (sock->sk->daddr == current->curr_ip))) {
++ current->used_accept = 0;
++ current->curr_ip = 0;
++ }
++#endif
++
+ sock_release(socki_lookup(inode));
++
+ return 0;
+ }
+
+@@ -903,6 +929,16 @@
+ int retval;
+ struct socket *sock;
+
++ if(!gr_search_socket(family, type, protocol)) {
++ retval = -EACCES;
++ goto out;
++ }
++
++ if (gr_handle_sock_all(family, type, protocol)) {
++ retval = -EACCES;
++ goto out;
++ }
++
+ retval = sock_create(family, type, protocol, &sock);
+ if (retval < 0)
+ goto out;
+@@ -998,12 +1034,26 @@
+ {
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
++ struct sockaddr * sck;
+ int err;
+
+ if((sock = sockfd_lookup(fd,&err))!=NULL)
+ {
+- if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0)
++ if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
++ sck = (struct sockaddr *) address;
++
++ if(!gr_search_bind(sock, (struct sockaddr_in *) sck)) {
++ sockfd_put(sock);
++ return -EACCES;
++ }
++
++ if (gr_handle_sock_server(sck)) {
++ sockfd_put(sock);
++ return -EACCES;
++ }
++
+ err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
++ }
+ sockfd_put(sock);
+ }
+ return err;
+@@ -1079,6 +1129,8 @@
+ if ((err = sock_map_fd(newsock)) < 0)
+ goto out_release;
+
++ gr_attach_curr_ip(newsock->sk);
++
+ out_put:
+ sockfd_put(sock);
+ out:
+@@ -1106,6 +1158,7 @@
+ {
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
++ struct sockaddr * sck;
+ int err;
+
+ sock = sockfd_lookup(fd, &err);
+@@ -1114,6 +1167,24 @@
+ err = move_addr_to_kernel(uservaddr, addrlen, address);
+ if (err < 0)
+ goto out_put;
++
++ sck = (struct sockaddr *) address;
++
++ if (!gr_search_connect(sock, (struct sockaddr_in *) sck)) {
++ err = -EACCES;
++ goto out_put;
++ }
++
++ if (gr_handle_sock_client(sck)) {
++ err = -EACCES;
++ goto out_put;
++ }
++
++#ifdef CONFIG_GRKERNSEC
++ if (sock->sk->protocol == IPPROTO_TCP)
++ current->used_connect = 1;
++#endif
++
+ err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen,
+ sock->file->f_flags);
+ out_put:
+@@ -1333,6 +1404,14 @@
+ err=sock->ops->shutdown(sock, how);
+ sockfd_put(sock);
+ }
++
++#ifdef CONFIG_GRKERNSEC
++ if (likely(!err && current->used_accept)) {
++ current->used_accept = 0;
++ current->curr_ip = 0;
++ }
++#endif
++
+ return err;
+ }
+
+diff -urN linux-2.4.21/net/sunrpc/xprt.c linux-2.4.21/net/sunrpc/xprt.c
+--- linux-2.4.21/net/sunrpc/xprt.c 2003-06-23 11:41:57.000000000 -0400
++++ linux-2.4.21/net/sunrpc/xprt.c 2003-06-23 11:49:17.000000000 -0400
+@@ -59,6 +59,7 @@
+ #include <linux/unistd.h>
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/file.h>
++#include <linux/grsecurity.h>
+
+ #include <net/sock.h>
+ #include <net/checksum.h>
+@@ -1267,6 +1268,12 @@
+ }
+ ret = xid++;
+ spin_unlock(&xid_lock);
++
++#ifdef CONFIG_GRKERNSEC_RANDRPC
++ if (grsec_enable_randrpc)
++ ret = arc4random();
++#endif
++
+ return ret;
+ }
+
+diff -urN linux-2.4.21/net/unix/af_unix.c linux-2.4.21/net/unix/af_unix.c
+--- linux-2.4.21/net/unix/af_unix.c 2003-06-23 11:41:53.000000000 -0400
++++ linux-2.4.21/net/unix/af_unix.c 2003-06-23 11:49:18.000000000 -0400
+@@ -109,6 +109,7 @@
+ #include <linux/poll.h>
+ #include <linux/smp_lock.h>
+ #include <linux/rtnetlink.h>
++#include <linux/grsecurity.h>
+
+ #include <asm/checksum.h>
+
+@@ -599,6 +600,11 @@
+ if (err)
+ goto put_fail;
+
++ if (!gr_acl_handle_unix(nd.dentry, nd.mnt)) {
++ err = -EACCES;
++ goto put_fail;
++ }
++
+ err = -ECONNREFUSED;
+ if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
+ goto put_fail;
+@@ -622,6 +628,13 @@
+ if (u) {
+ struct dentry *dentry;
+ dentry = u->protinfo.af_unix.dentry;
++
++ if (!gr_handle_chroot_unix(u->peercred.pid)) {
++ err = -EPERM;
++ sock_put(u);
++ goto fail;
++ }
++
+ if (dentry)
+ UPDATE_ATIME(dentry->d_inode);
+ } else
+@@ -720,9 +733,19 @@
+ * All right, let's create it.
+ */
+ mode = S_IFSOCK | (sock->inode->i_mode & ~current->fs->umask);
++
++ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
++ err = -EACCES;
++ goto out_mknod_dput;
++ }
++
+ err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
++
+ if (err)
+ goto out_mknod_dput;
++
++ gr_handle_create(dentry, nd.mnt);
++
+ up(&nd.dentry->d_inode->i_sem);
+ dput(nd.dentry);
+ nd.dentry = dentry;
+@@ -740,6 +763,10 @@
+ goto out_unlock;
+ }
+
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
++ sk->peercred.pid = current->pid;
++#endif
++
+ list = &unix_socket_table[addr->hash];
+ } else {
+ list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
+@@ -866,6 +893,9 @@
+ int st;
+ int err;
+ long timeo;
++#ifdef CONFIG_GRKERNSEC
++ struct task_struct *p, **htable;
++#endif
+
+ err = unix_mkname(sunaddr, addr_len, &hash);
+ if (err < 0)
+@@ -989,6 +1019,17 @@
+ /* Set credentials */
+ sk->peercred = other->peercred;
+
++#ifdef CONFIG_GRKERNSEC
++ read_lock(&tasklist_lock);
++ htable = &pidhash[pid_hashfn(other->peercred.pid)];
++ for (p = *htable; p && p->pid != other->peercred.pid; p = p->pidhash_next);
++ if (p) {
++ p->curr_ip = current->curr_ip;
++ p->used_accept = 1;
++ }
++ read_unlock(&tasklist_lock);
++#endif
++
+ sock_hold(newsk);
+ unix_peer(sk)=newsk;
+ sock->state=SS_CONNECTED;