From:

Example Brains Source Code Files

[0001] Below are example files associated with a 'brain' according to specific embodiments of the present invention and associated with an example embodiment using a dual-system where programs marked for deception are executed on a different system. In this case, a wrapper program as described herein according to specific embodiments of the invention is in interprocess communication (IPC) with a Brain module as described and the Brain module determines whether to run the command on a different system. Thus, in this example source code, actions include allowing a program to execute normally or redirect a program to a second computer. This example further can provide a fictitious error and/or can refuse to allow a program to execute. This example source code further includes files necessary for the interprocess communication between the IPCwrapper program and the 'brain'.

# File allowed.lisp

(setq commands (make-hash-table :test 'equal))

(setf (gethash "/bin/bash" commands) 'allowed)

(setf (gethash "/bin/cat" commands) 'allowed)

(setf (gethash "/bin/cp" commands) 'allowed)

(setf (gethash "/bin/df" commands) 'allowed)

(setf (gethash "/bin/dircolors" commands) 'allowed)

(setf (gethash "/bin/grep" commands) 'allowed)

(setf (gethash "/bin/hostname" commands) 'allowed)

(setf (gethash "/bin/id" commands) 'allowed)

(setf (gethash "/bin/login" commands) 'allowed)

(setf (gethash "/bin/ps" commands) 'allowed)

(setf (gethash "/bin/rm" commands) 'allowed)

(setf (gethash "/bin/sh" commands) 'allowed)

(setf (gethash "/bin/tput" commands) 'allowed)

(setf (gethash "/sbin/mingetty" commands) 'allowed)

(setf (gethash "/sbin/modprobe" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/X" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/blackbox" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/bsetroot" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/mozilla/run-mozilla.sh" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/startx" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/xauth" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/xinit" commands) 'allowed)

(setf (gethash "/usr/X11R6/bin/xterm" commands) 'allowed)

(setf (gethash "/usr/X11R6/lib/X11/xkb/xkbcomp" commands) 'allowed)

(setf (gethash "/usr/bin/basename" commands) 'allowed)

(setf (gethash "/usr/bin/date" commands) 'allowed)

(setf (gethash "/usr/bin/dirname" commands) 'allowed)

(setf (gethash "/usr/bin/du" commands) 'allowed)

(setf (gethash "/usr/bin/find" commands) 'allowed)

(setf (gethash "/usr/bin/mcookie" commands) 'allowed)

(setf (gethash "/usr/bin/sort" commands) 'allowed)

(setf (gethash "/usr/bin/stty" commands) 'allowed)

(setf (gethash "/usr/bin/tail" commands) 'allowed)

(setf (gethash "/usr/local/bin/me" commands) 'allowed)

(setf (gethash "/usr/local/bin/which" commands) 'allowed)

# File brain.lisp

(use-package "QLISP")

; NOTES

; -----

; Type < -256 && type < 0 : bounce to some other system

; Type < 0 : fail and print this error string

; Type = 0 : execute the command

; Type > 0 && type < 256 : sleep and check again

; Type > 256 : do this thing

;

; MOODS

; -----

; -3 == >:( Angry: Do mean things.

; -2 == :| Cautious: Deny only questionable commands.

; -1 == :O Scared: Stop requests at the wrapper, preventing floods. (Sample
; code for this option is not included herein

; 0 == :) Happy: Don't do much of anything. Defalut setting for good users.

; MODES

; -----

; 0 == Normal.

; 1 == Obnoxious.

;============================================

(qinit)

(defstruct response command type mood command-history response-history)

(setq *responsetable* (make-hash-table))

(setq *no-bounce-ips* 3)

(load "allowed.lisp")

; initialize questionable commands

(setf (gethash "/bin/rm" commands) 'questionable)

; initialize bad commands

(setf (gethash "/bin/dd" commands) 'bad)

(setf (gethash "/bin/ln" commands) 'bad)

(setf (gethash "/bin/mknod" commands) 'bad)

(setf (gethash "/bin/mount" commands) 'bad)

(setf (gethash "/sbin/fdisk" commands) 'bad)

(setf (gethash "/usr/bin/su" commands) 'bad)

(setq *bounce-ips* (make-array *no-bounce-ips* :initial-contents '("10.0.0.123" "10.0.0.58" "10.0.30.2")))

(setq *resp-mode* 0)

;============================================

(defun do-output (id &aux struct)

(setq struct (gethash id *responsetable*))

(qsnd (response-type struct) (generate-response-string (response-command struct) (response-type struct)))

)

;============================================

;(defun brain-demo ()

;)

;============================================

(defun handler ()

(prog (data-in id command)

(setq data-in (qget))

(setq id (intern (car-string data-in)))

(setq command (cdr-string data-in))

(save-response command id)

(do-output id)

)

)

;============================================

(defun save-response (command id)

(prog (struct mood responsetype t-c-hist t-r-hist)

(setq struct (gethash id *responsetable*))

(if (null struct) (progn (add-response id)

(setq mood (decide-mood command id))

(setq responsetype (set-response-type command mood))

(setq t-c-hist (list command))

(setq t-r-hist (list responsetype)))

(progn (if (> (response-mood struct) (decide-mood command id)) (setq mood (decide-mood command id))

(setq mood (response-mood struct)))

(setq responsetype (set-response-type command mood))

(setq t-c-hist (build-history command (response-command-history struct)))

(setq t-r-hist (build-history responsetype (response-response-history struct))))

)

(add-response id command responsetype mood t-c-hist t-r-hist)

(return t)

)

)

;============================================

(defun generate-response-string (command responsetype)

(prog ()

(cond ((>= -256 responsetype) (return (get-ip responsetype)))

((> 0 responsetype -256) (return (failure-for-errno responsetype command)))

((= 0 responsetype) (return "run"))

((< 0 responsetype 255) (return "wait"))

((= 255 responsetype) (return "kill"))

((>= responsetype 256) (return "do something"))

(t (return (failure-for-errno -1 command)))

)

)

)

;============================================

(defun build-history (command buff)

(if (equal 9 (length buff)) (setq buff (cdr buff)))

(append buff (list command))

)

;============================================

(defun add-response (id &optional command type mood commandh responseh)

(prog (struct)

(setq struct (make-response :command command :type type :mood mood :command-history commandh :response-history responseh))

(setf (gethash id *responsetable*) struct)

(return struct)

)

)

;============================================

(defun decide-mood (command id)

(prog (q r)

(setq q (is-command 'questionable command))

(setq r (is-trouble id))

(if (is-command 'bad command) (return -3))

(if (and q r) (return -2))

(return 0)

)

)

;============================================

(defun set-response-type (command mood)

(prog (quest allow)

(setq quest (is-command 'questionable command))

(setq allow (is-command 'allowed command))

(setq bad (is-command 'bad command))

(cond

((= *resp-mode* 0)

(cond ((and (= mood 0) allow) (return 0))

((and (= mood 0) (not allow)) (return -258))

((and (= mood -2) quest) (return (rand-resp 'nice)))

((and (= mood -2) allow) (return 0))

((= mood -3) (return -258))

(bad (return (rand-resp 'nice)))

))

((= *resp-mode* 1)

(cond ((and (= mood 0) allow) (return 0))

((and (= mood 0) (not allow)) (return -1))

((and (= mood -2) quest) (return (rand-resp 'mean)))

((and (= mood -2) allow) (return 0))

((= mood -3) (return -256))

(bad (return (rand-resp 'mean)))

))

)

)

)

;============================================

(defun is-command (type command)

(let ((realtype (gethash command commands)))

(equal realtype type)

)

)

;============================================

(defun set-mode (new_mode)

(setq *resp-mode* new_mode)

)

;============================================

(defun is-trouble (id)

(prog (history hsize count element trouble-count)

(setq history (remember-history id 'command))

(if (null history) (return nil))

(setq hsize (length history))

(setq count 0)

(setq trouble-count 0)

again

(setq element (aref history count))

(if (is-command 'questionable element) (setq trouble-count (1+ trouble-count)))

(setq count (1+ count))

(if (< count hsize) (go again))

(if (>= trouble-count 4) (return t) (return nil))

)

)

;============================================

(defun calc-ip-index (response)

(prog ()

(return (- (abs (+ response 255)) 1))

)

)

;============================================

(defun get-ip (response)

(prog ()

(return (aref *bounce-ips* (calc-ip-index response)))

)

)

;============================================

(defun dump-response (id &aux struct)

(prog ()

(setq struct (gethash id *responsetable*))

(print id)

(terpri)

(princ "Command: ")

(prin1 (response-command struct)) ;Command the response was generated for (internal book-keeping)

(terpri)

(princ "Response: ")

(prin1 (response-type struct)) ;Type of response

(terpri)

(princ "Mood: ")

(prin1 (response-mood struct)) ;Mood the brain's in for that ID.

(terpri)

(princ "Command History: ")

(prin1 (response-command-history struct)) ;Track history of what's been responded to. (internal book-keeping)

(terpri)

(princ "Response History: ")

(prin1 (response-response-history struct)) ;Track history of what responses have been used. (internal book-keeping)

(terpri)

(return t)

)

)

;============================================

(defun remember-history (id history-to-load)

(prog (hist harray struct)

(setq struct (gethash id *responsetable*))

(if (null (response-command-history struct)) (return nil))

(if (null (response-response-history struct)) (return nil))

(cond ((equal history-to-load 'command) (setq hist (response-command-history struct))

(setq harray (make-array (length hist) :initial-contents hist)))

((equal history-to-load 'response) (setq hist (response-response-history struct))

(setq harray (make-array (length hist) :initial-contents hist)))

)

(return harray)

)

)

;============================================

(defun found-in-history (id command history-type)

(prog (history hsize count element element_count)

(setq history (remember-history id history-type))

(if (null history) (return nil))

(setq hsize (length history))

(setq count 0)

(setq element_count 0)

again

(setq element (aref history count))

(if (equal element command) (setq element_count (1+ element_count)))

(setq count (1+ count))

(if (< count hsize) (go again))

(if (not (= element_count 0)) (return element_count))

(if (= element_count 0) (return nil))

)

)

;============================================

(defun last-instance (id command)

(prog (history hsize count element responses)

(setq history (remember-history id 'command))

(if (null history) (return nil))

(setq responses (remember-history id 'response))

(if (null responses) (return nil))

(setq hsize (length history))

(setq count 0)

again

(setq element (aref history count))

(if (equal element command) (return (aref responses count)))

(setq count (1+ count))

(if (< count hsize) (go again))

(return nil)

)

)

;============================================

(defun rand-resp (mode)

(prog ()

(cond ((equal mode 'nice) (return (- 0 (random 124))))

((equal mode 'mean) (return (- 0 (+ 124 (random 18)))))

(t (return -1))

)

)

)

;============================================

(defun failure-for-errno (x command) ;x = response type

(prog ()

(cond ((= x -1) (return (format nil "~A: Operation not permitted" (string-downcase (format nil "~:A" command)))))

((= x -2) (return (format nil "~A: No such file or directory" (string-downcase (format nil "~:A" command)))))

((= x -3) (return (format nil "~A: No such process" (string-downcase (format nil "~:A" command)))))

((= x -4) (return (format nil "~A: Interrupted system call" (string-downcase (format nil "~:A" command)))))

((= x -5) (return (format nil "~A: Inpur/output error" (string-downcase (format nil "~:A" command)))))

((= x -6) (return (format nil "~A: No such device or address" (string-downcase (format nil "~:A" command)))))

((= x -7) (return (format nil "~A: Argument list too long" (string-downcase (format nil "~:A" command)))))

((= x -8) (return (format nil "~A: Exec format error" (string-downcase (format nil "~:A" command)))))

((= x -9) (return (format nil "~A: Bad file descriptor" (string-downcase (format nil "~:A" command)))))

((= x -10) (return (format nil "~A: No child processes" (string-downcase (format nil "~:A" command)))))

((= x -11) (return (format nil "~A: Resource temporarily unavailable" (string-downcase (format nil "~:A" command)))))

((= x -12) (return (format nil "~A: Cannot allocate memory" (string-downcase (format nil "~:A" command)))))

((= x -13) (return (format nil "~A: Permission denied" (string-downcase (format nil "~:A" command)))))

((= x -14) (return (format nil "~A: Bad address" (string-downcase (format nil "~:A" command)))))

((= x -15) (return (format nil "~A: Block device required" (string-downcase (format nil "~:A" command)))))

((= x -16) (return (format nil "~A: Device or resource busy" (string-downcase (format nil "~:A" command)))))

((= x -17) (return (format nil "~A: File exists" (string-downcase (format nil "~:A" command)))))

((= x -18) (return (format nil "~A: Invalid cross-device link" (string-downcase (format nil "~:A" command)))))

((= x -19) (return (format nil "~A: No such device" (string-downcase (format nil "~:A" command)))))

((= x -20) (return (format nil "~A: Not a directory" (string-downcase (format nil "~:A" command)))))

((= x -21) (return (format nil "~A: Is a directory" (string-downcase (format nil "~:A" command)))))

((= x -22) (return (format nil "~A: Invalid argument" (string-downcase (format nil "~:A" command)))))

((= x -23) (return (format nil "~A: Too many open files in system" (string-downcase (format nil "~:A" command)))))

((= x -24) (return (format nil "~A: Too many open files" (string-downcase (format nil "~:A" command)))))

((= x -25) (return (format nil "~A: Inappropriate ioctl for device" (string-downcase (format nil "~:A" command)))))

((= x -26) (return (format nil "~A: Text file busy" (string-downcase (format nil "~:A" command)))))

((= x -27) (return (format nil "~A: File too large" (string-downcase (format nil "~:A" command)))))

((= x -28) (return (format nil "~A: No space left on device" (string-downcase (format nil "~:A" command)))))

((= x -29) (return (format nil "~A: Illegal seek" (string-downcase (format nil "~:A" command)))))

((= x -30) (return (format nil "~A: Read-only file system" (string-downcase (format nil "~:A" command)))))

((= x -31) (return (format nil "~A: Too many links" (string-downcase (format nil "~:A" command)))))

((= x -32) (return (format nil "~A: Broken pipe" (string-downcase (format nil "~:A" command)))))

((= x -33) (return (format nil "~A: Numerical argument out of domain" (string-downcase (format nil "~:A" command)))))

((= x -34) (return (format nil "~A: Numerical result out of range" (string-downcase (format nil "~:A" command)))))

((= x -35) (return (format nil "~A: Resource deadlock avoided" (string-downcase (format nil "~:A" command)))))

((= x -36) (return (format nil "~A: File name too long" (string-downcase (format nil "~:A" command)))))

((= x -37) (return (format nil "~A: No locks available" (string-downcase (format nil "~:A" command)))))

((= x -38) (return (format nil "~A: Function not implemented" (string-downcase (format nil "~:A" command)))))

((= x -39) (return (format nil "~A: Directory not empty" (string-downcase (format nil "~:A" command)))))

((= x -40) (return (format nil "~A: Too many levels of symbolic links" (string-downcase (format nil "~:A" command)))))

((= x -41) (return (format nil "~A: Unknown error 41" (string-downcase (format nil "~:A" command)))))

((= x -42) (return (format nil "~A: No message of desired type" (string-downcase (format nil "~:A" command)))))

((= x -43) (return (format nil "~A: Identifier removed" (string-downcase (format nil "~:A" command)))))

((= x -44) (return (format nil "~A: Channel number out of range" (string-downcase (format nil "~:A" command)))))

((= x -45) (return (format nil "~A: Level 2 not synchronized" (string-downcase (format nil "~:A" command)))))

((= x -46) (return (format nil "~A: Level 3 halted" (string-downcase (format nil "~:A" command)))))

((= x -47) (return (format nil "~A: Level 3 reset" (string-downcase (format nil "~:A" command)))))

((= x -48) (return (format nil "~A: Link number out of range" (string-downcase (format nil "~:A" command)))))

((= x -49) (return (format nil "~A: Protocol driver not attached" (string-downcase (format nil "~:A" command)))))

((= x -50) (return (format nil "~A: No CSI structure available" (string-downcase (format nil "~:A" command)))))

((= x -51) (return (format nil "~A: Level 2 halted" (string-downcase (format nil "~:A" command)))))

((= x -52) (return (format nil "~A: Invalid exchange" (string-downcase (format nil "~:A" command)))))

((= x -53) (return (format nil "~A: Invalid request descriptor" (string-downcase (format nil "~:A" command)))))

((= x -54) (return (format nil "~A: Exchange full" (string-downcase (format nil "~:A" command)))))

((= x -55) (return (format nil "~A: No anode" (string-downcase (format nil "~:A" command)))))

((= x -56) (return (format nil "~A: Invalid request code" (string-downcase (format nil "~:A" command)))))

((= x -57) (return (format nil "~A: Invalid slot" (string-downcase (format nil "~:A" command)))))

((= x -58) (return (format nil "~A: Unknown error 58" (string-downcase (format nil "~:A" command)))))

((= x -59) (return (format nil "~A: Bad font file format" (string-downcase (format nil "~:A" command)))))

((= x -60) (return (format nil "~A: Device not a stream" (string-downcase (format nil "~:A" command)))))

((= x -61) (return (format nil "~A: No data available" (string-downcase (format nil "~:A" command)))))

((= x -62) (return (format nil "~A: Timer expired" (string-downcase (format nil "~:A" command)))))

((= x -63) (return (format nil "~A: Out of streams resources" (string-downcase (format nil "~:A" command)))))

((= x -64) (return (format nil "~A: Machine is not on the network" (string-downcase (format nil "~:A" command)))))

((= x -65) (return (format nil "~A: Package not installed" (string-downcase (format nil "~:A" command)))))

((= x -66) (return (format nil "~A: Object is remote" (string-downcase (format nil "~:A" command)))))

((= x -67) (return (format nil "~A: Link has been severed" (string-downcase (format nil "~:A" command)))))

((= x -68) (return (format nil "~A: Advertise error" (string-downcase (format nil "~:A" command)))))

((= x -69) (return (format nil "~A: Srmount error" (string-downcase (format nil "~:A" command)))))

((= x -70) (return (format nil "~A: Communication error on send" (string-downcase (format nil "~:A" command)))))

((= x -71) (return (format nil "~A: Protocol error" (string-downcase (format nil "~:A" command)))))

((= x -72) (return (format nil "~A: Multihop attempted" (string-downcase (format nil "~:A" command)))))

((= x -73) (return (format nil "~A: RFS specific error" (string-downcase (format nil "~:A" command)))))

((= x -74) (return (format nil "~A: Bad message" (string-downcase (format nil "~:A" command)))))

((= x -75) (return (format nil "~A: Value too large for defined data type" (string-downcase (format nil "~:A" command)))))

((= x -76) (return (format nil "~A: Name not unique on network" (string-downcase (format nil "~:A" command)))))

((= x -77) (return (format nil "~A: File descriptor in bad state" (string-downcase (format nil "~:A" command)))))

((= x -78) (return (format nil "~A: Remote address changed" (string-downcase (format nil "~:A" command)))))

((= x -79) (return (format nil "~A: Can not access a needed shared library" (string-downcase (format nil "~:A" command)))))

((= x -80) (return (format nil "~A: Accessing a corrupted shared library" (string-downcase (format nil "~:A" command)))))

((= x -81) (return (format nil "~A: .lib section in a.out corrupted" (string-downcase (format nil "~:A" command)))))

((= x -82) (return (format nil "~A: Attempting to link in too many shared libraries" (string-downcase (format nil "~:A" command)))))

((= x -83) (return (format nil "~A: Cannot exec a shared library directly" (string-downcase (format nil "~:A" command)))))

((= x -84) (return (format nil "~A: Invalid or incomplete multibyte or wide character" (string-downcase (format nil "~:A" command)))))

((= x -85) (return (format nil "~A: Interrupted system call should be restarted" (string-downcase (format nil "~:A" command)))))

((= x -86) (return (format nil "~A: Streams pipe error" (string-downcase (format nil "~:A" command)))))

((= x -87) (return (format nil "~A: Too many users" (string-downcase (format nil "~:A" command)))))

((= x -88) (return (format nil "~A: Socket operation on non-socket" (string-downcase (format nil "~:A" command)))))

((= x -89) (return (format nil "~A: Destination address required" (string-downcase (format nil "~:A" command)))))

((= x -90) (return (format nil "~A: Message too long" (string-downcase (format nil "~:A" command)))))

((= x -91) (return (format nil "~A: Protocol wrong type for socket" (string-downcase (format nil "~:A" command)))))

((= x -92) (return (format nil "~A: Protocol not available" (string-downcase (format nil "~:A" command)))))

((= x -93) (return (format nil "~A: Protocol not supported" (string-downcase (format nil "~:A" command)))))

((= x -94) (return (format nil "~A: Socket type not supported" (string-downcase (format nil "~:A" command)))))

((= x -95) (return (format nil "~A: Operation not supported" (string-downcase (format nil "~:A" command)))))

((= x -96) (return (format nil "~A: Protocol family not supported" (string-downcase (format nil "~:A" command)))))

((= x -97) (return (format nil "~A: Address family not supported by protocol" (string-downcase (format nil "~:A" command)))))

((= x -98) (return (format nil "~A: Address already in use" (string-downcase (format nil "~:A" command)))))

((= x -99) (return (format nil "~A: Cannot assign requested address" (string-downcase (format nil "~:A" command)))))

((= x -100) (return (format nil "~A: Network is down" (string-downcase (format nil "~:A" command)))))

((= x -101) (return (format nil "~A: Network is unreachable" (string-downcase (format nil "~:A" command)))))

((= x -102) (return (format nil "~A: Network dropped connection because of reset" (string-downcase (format nil "~:A" command)))))

((= x -103) (return (format nil "~A: Software caused connection abort" (string-downcase (format nil "~:A" command)))))

((= x -104) (return (format nil "~A: Connection reset by peer" (string-downcase (format nil "~:A" command)))))

((= x -105) (return (format nil "~A: No buffer space available" (string-downcase (format nil "~:A" command)))))

((= x -106) (return (format nil "~A: Transport endpoint is already connected" (string-downcase (format nil "~:A" command)))))

((= x -107) (return (format nil "~A: Transport endpoint is not connected" (string-downcase (format nil "~:A" command)))))

((= x -108) (return (format nil "~A: Cannot send after transport endpoint shutdown" (string-downcase (format nil "~:A" command)))))

((= x -109) (return (format nil "~A: Too many references: cannot splice" (string-downcase (format nil "~:A" command)))))

((= x -110) (return (format nil "~A: Connection timed out" (string-downcase (format nil "~:A" command)))))

((= x -111) (return (format nil "~A: Connection refused" (string-downcase (format nil "~:A" command)))))

((= x -112) (return (format nil "~A: Host is down" (string-downcase (format nil "~:A" command)))))

((= x -113) (return (format nil "~A: No route to host" (string-downcase (format nil "~:A" command)))))

((= x -114) (return (format nil "~A: Operation already in progress" (string-downcase (format nil "~:A" command)))))

((= x -115) (return (format nil "~A: Operation now in progress" (string-downcase (format nil "~:A" command)))))

((= x -116) (return (format nil "~A: Stale NFS file handle" (string-downcase (format nil "~:A" command)))))

((= x -117) (return (format nil "~A: Structure needs cleaning" (string-downcase (format nil "~:A" command)))))

((= x -118) (return (format nil "~A: Not a XENIX named type file" (string-downcase (format nil "~:A" command)))))

((= x -119) (return (format nil "~A: No XENIX semaphores available" (string-downcase (format nil "~:A" command)))))

((= x -120) (return (format nil "~A: Is a named type file" (string-downcase (format nil "~:A" command)))))

((= x -121) (return (format nil "~A: Remote I/O error" (string-downcase (format nil "~:A" command)))))

((= x -122) (return (format nil "~A: Disk quota exceeded" (string-downcase (format nil "~:A" command)))))

((= x -123) (return (format nil "~A: No medium found" (string-downcase (format nil "~:A" command)))))

((= x -124) (return (format nil "~A: Wrong medium type" (string-downcase (format nil "~:A" command)))))

;---------------------------------------OBNOXIOUS RESPONSES--------------------------

((= x -125) (return (format nil "~A: Memory Spillage has occured! Please clean up and try again." (string-downcase (format nil "~:A" command)))))

((= x -126) (return (format nil "~A: General logic fault, slipped on a 1! Did you remember to clean up your memory spill?" (string-downcase (format nil "~:A" command)))))

((= x -127) (return (format nil "~A: General logic fault, slipped on a 0! Did you remember to clean up your memory spill?" (string-downcase (format nil "~:A" command)))))

((= x -128) (return (format nil "~A: .lib section in a.out corrupted" (string-downcase (format nil "~:A" command)))))

((= x -129) (return (format nil "~A: Argh! File not found!" (string-downcase (format nil "~:A" command)))))

((= x -130) (return (format nil "~A: We never had this conversation, now shred that document." (string-downcase (format nil "~:A" command)))))

((= x -131) (return (format nil "~A: Oh yeah, what's in it for me?" (string-downcase (format nil "~:A" command)))))

((= x -132) (return (format nil "~A: I don't wanna." (string-downcase (format nil "~:A" command)))))

((= x -133) (return (format nil "~A: Illegal byte sequence. What are you thinking?" (string-downcase (format nil "~:A" command)))))

((= x -134) (return (format nil "~A: File descriptor in bad state. Looks like you really screwed up this time!" (string-downcase (format nil "~:A" command)))))

((= x -135) (return (format nil "~A: Would you like to play a game?" (string-downcase (format nil "~:A" command)))))

((= x -136) (return (format nil "~A: 50483333524D796C333354536B96313153. I feel sick. =(" (string-downcase (format nil "~:A" command)))))

((= x -137) (return (format nil "~A: Logic dirty! Please wash computer and try again." (string-downcase (format nil "~:A" command)))))

((= x -138) (return (format nil "~A: Fractal radiation jamming the backbone." (string-downcase (format nil "~:A" command)))))

((= x -139) (return (format nil "~A: I/O dam collapsed. Run for your life!!!" (string-downcase (format nil "~:A" command)))))

((= x -140) (return (format nil "~A: PC load letter." (string-downcase (format nil "~:A" command)))))

((= x -141) (return (format nil "~A: General protection fault! ... Recovered." (string-downcase (format nil "~:A" command)))))

((= x -142) (return (format nil "~A: Kernel panic! ... Recovered." (string-downcase (format nil "~:A" command)))))

;-------------------------------DEFAULT RESPONSE-------------------------------

(t (return (format nil "~A: Operation not permitted" (string-downcase (format nil "~:A" command)))))

)

)

)

(qinit)

;============================================

(defun first-string (list)

(do

((x list (cdr x)) (res nil (format nil "~:A~:A" res (car x))))

((equal (car x) '#\Space) res)

(if (atom x) (return res))

(if (null x) (return nil))

)

)

;============================================

(defun car-string (string)

(prog ()

(setq list (coerce string 'list))

(setq element (string-left-trim "()" (first-string list)))

(return element)

)

)

;============================================

(defun cdr-string (string)

(prog ()

(setq list (coerce string 'list))

(setq element (first-string list))

(if (equal element nil) (return nil))

(string-left-trim "()" element)

(setq rest (string-left-trim " " (string-left-trim element string)))

(return rest)

)

)

;============================================

(defun brain () (progn (qinit) (loop (handler)) ))

(defun stubbrain () (progn (qinit) (loop (qget) (qsnd 0 "ok"))))

# File brain-null

if test -f brain.fas

then if test brain.lisp -ot brain.fas; then B="brain.fas"; else B="brain.lisp"; fi

else B="brain.lisp";fi

export B

echo "$B"

if test -f $1

then

/usr/local/lib/clisp/base/qlisp/lisp.run -B /usr/local/lib/clisp \

-q -M /usr/local/lib/clisp/base/qlisp/lispinit.mem \

-i call-qfunc -i $B -x "(in-package \"QLISP\") (stubbrain \"$1\")"

else

echo "# No such file as $1"

fi

# File brain-run

if test -f brain.fas

then if test brain.lisp -ot brain.fas; then B="brain.fas"; else B="brain.lisp"; fi

else B="brain.lisp";fi

export B

echo "$B"

if test -f $1

then

/usr/local/lib/clisp/base/qlisp/lisp.run -B /usr/local/lib/clisp \

-q -M /usr/local/lib/clisp/base/qlisp/lispinit.mem \

-i call-qfunc -i $B -x "(in-package \"QLISP\") (brain \"$1\")"

else

echo "# No such file as $1"

fi

# File call-qfunc.c

#include "clisp.h"

extern object module__call_qfunc__object_tab[];

subr_ module__call_qfunc__subr_tab[1];

uintC module__call_qfunc__subr_tab_size = 0;

subr_initdata module__call_qfunc__subr_tab_initdata[1];

object module__call_qfunc__object_tab[1];

object_initdata module__call_qfunc__object_tab_initdata[1];

uintC module__call_qfunc__object_tab_size = 0;

extern int (qinit)();

extern char* (qget)();

extern int (qsnd)();

extern int (qdestroy)();

void module__call_qfunc__init_function_1(module)

var module_* module;

{ }

void module__call_qfunc__init_function_2(module)

var module_* module;

{

register_foreign_function(&qinit,"qinit",1024);

register_foreign_function(&qget,"qget",1024);

register_foreign_function(&qsnd,"qsnd",1024);

register_foreign_function(&qdestroy,"qdestroy",1024);

}

# File call-qfunc.lisp

;Copyright - Sandia National Laboratories 2002

;By Chris Muelder

;Lisp interface to qfunc.c

(DEFPACKAGE "QLISP" (:use "LISP" "FFI"))

(IN-PACKAGE "QLISP")

(export 'qinit)

(export 'qget)

(export 'qsnd)

(export 'qdestroy)

(def-c-call-out qinit (:return-type int))

(def-c-call-out qget (:return-type c-string))

(def-c-call-out qsnd (:arguments (code int) (msg c-string) )(:return-type int))

(def-c-call-out qdestroy (:return-type int))

# File maker

base=/usr/local/lib/clisp/base;export base

rm -rf ${base}/qlisp

export CLISP_LINKKIT=/usr/local/lib/clisp/linkkit/

rm -rf call-qfunc.c call-qfunc.o call-qfunc.lisp.fas qlisp.lib qlisp qlispout

/usr/local/lib/clisp/clisp-link create-module-set qlisp call-qfunc.c

cc -O -c qfunc.c

cd qlisp

ln -s ../qfunc.o qfunc.o

cp -f ../thingtofix link.sh

cd ..

${base}/lisp.run -M ${base}/lispinit.mem -q -c call-qfunc.lisp

/usr/local/lib/clisp/clisp-link add-module-set qlisp ${base} ${base}/qlisp

echo "(exit)" | ${base}/qlisp/lisp.run -q -M ${base}/qlisp/lispinit.mem -i call-qfunc

${base}/qlisp/lisp.run -q -M ${base}/qlisp/lispinit.mem -q -i call-qfunc -c brain.lisp

echo "(compile-file \"brain.lisp\")" | ${base}/qlisp/lisp.run -q -M ${base}/qlisp/lispinit.mem -q -i call-qfunc

echo "Run with ${base}/qlisp/lisp.run -M ${base}/qlisp/lispinit.mem -i call-qfunc.fas"

# File qfunc.c

/* Copyright - Sandia National Laboratories 2002

* Functions to generate and destroy SysV queues, and to get&send data to it

*/

#include<stdio.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

#include <syscall.h>

#include <errno.h>

#include <unistd.h>

/* #define __NR_ad 0

_syscall1(long,ad,int,foo); */

#define _MSG_SIZE_ 255

struct msgbuf

{int mtype;

int32_t opcode;

char mtext[_MSG_SIZE_];

};

int32_t qid=-1;

struct msgbuf qmsg;

char buff[_MSG_SIZE_];

int qinit(){qid=msgget((key_t) (12345), 0777 | IPC_CREAT);return(qid);}

char * qget()

{FILE * f;

printf("getting\n");

while(1)

{

// msgrcv(qid, &qmsg, sizeof(struct msgbuf), 0, MSG_NOERROR);

msgrcv(qid, &qmsg, sizeof(struct msgbuf), 1, MSG_NOERROR);

printf("got a message\n");

// if(qmsg.mtype>65535||qmsg.mtype<0) continue;

printf("pid=%d, code=%d, string=%s\n", qmsg.mtype, qmsg.opcode, qmsg.mtext);

if(qmsg.mtype==1)

{

printf("its for me!\n");

//ad(qmsg.opcode);

//if(errno!=EAGAIN) continue;

// memcpy(msg, qmsg.mtext, _MSG_SIZE_);

//set mtype

qmsg.mtype=qmsg.opcode;

}

else

{

//ad(qmsg.mtype);

//if(errno==EAGAIN) msgsnd(qid, &qmsg, sizeof(struct msgbuf), IPC_NOWAIT);

msgsnd(qid, &qmsg, sizeof(struct msgbuf), IPC_NOWAIT);

continue;

}

return qmsg.mtext;

}

}

int qsnd(int32_t code, char * msg)

{printf("Sending\n");

qmsg.opcode=code;memcpy(qmsg.mtext, msg, _MSG_SIZE_);

return(msgsnd(qid, &qmsg, sizeof(struct msgbuf), IPC_NOWAIT));

}

int qdestroy(){return(msgctl(qid, IPC_RMID, NULL));}

/*int main(int argc, char**argv)

{

int code=0;

char msg[_MSG_SIZE_]="";

qinit();

while(1)

{

qget(&code, msg);

qsnd(42, "10.0.0.123");

}

qdestroy();

return 0;

}/*EOF*/

# File run

if test -f brain.fas

then if test brain.lisp -ot brain.fas; then B="brain.fas"; else B="brain.lisp"; fi

else B="brain.lisp";fi

export B

echo "$B"

if test "Z$0" = Z

then

/usr/local/lib/clisp/base/qlisp/lisp.run -q \

-M /usr/local/lib/clisp/base/qlisp/lispinit.mem \

-i call-qfunc -i $B -x '(in-package "QLISP")'

else

/usr/local/lib/clisp/base/qlisp/lisp.run -q \

-M /usr/local/lib/clisp/base/qlisp/lispinit.mem \

-i call-qfunc -i $B $*

fi

# File thingtofix

file_list='qfunc.o'

mod_list=''

if test -r call-qfunc.c; then

file_list="$file_list"' call-qfunc.o'

mod_list="$mod_list"' call_qfunc'

fi

make clisp-module CC="${CC}" CFLAGS="${CFLAGS}" INCLUDES="$absolute_linkkitdir"

NEW_FILES="$file_list"

NEW_LIBS="$file_list"

NEW_MODULES="$mod_list"

TO_LOAD=''

PLAC.go file 1

[0002] These 'PLAC.go' files perform automated startup of computers running the "White Glove" Linux distribution using deception kernel modifications according to specific embodiments of the present invention. These CD-based systems use these startup files so that the deception mechanism begins to operate at system startup. The is an example "PLAC.go" startup file for a network deception that redirects unauthorized programs to a secondary machine for execution.

cp -af /mnt/floppy/ssh /etc

mkdir /root/.ssh/

cp -f /mnt/floppy/known_hosts /root/.ssh

service sshd start

webser /cdrom-real/www

ifconfig eth0 10.0.30.1

#rm -rf /root/Trojan

#cp -f /mnt/floppy/wrapSSH.demo /root/wrap

# new for brains

cp -af /mnt/floppy/q2lisp /tmp/q2lisp

cd /tmp/q2lisp

chmod 700 maker;./maker

cd base+q2lisp

cp /mnt/floppy/brain.l .

cp /mnt/floppy/allowed.lisp .

./lisp.run -M lispinit.mem -i q2lisp.fas -i brain.l > /dev/null 2>/dev/null&

cp -f /mnt/floppy/brainwrap /root/wrap

This is the "PLAC.go" startup file for the recipient system:

cp -af /mnt/floppy/ssh /etc

mkdir /root/.ssh/

cp -f known_hosts /root/.ssh

service sshd start

webser /cdrom-real/www

ifconfig eth0 10.0.30.2

rm -rf /root/Trojan/

Example Wrapper files

[0003] The following includes all of the programs and build information associated with an example implementation of wrapper technology according to specific embodiments of the present invention . Each file is named on a line starting with '#'. The README file describes the other files. In this example code, different functions that can be performed by a wrapper are described and enabled as different wrapXX.c files. In this case, for example, wrapnull.c simply calls the original exec with the original arguments, after first making sure that it is not calling itself. It will be understood for the teachings herein that a single wrapper module will typically have several of the functions illustrated by the sample wrapXX.c code files below and in various implementations, all or most functions may be encoded in a single code file.

# File README

File name Description

--------------------------------------------------------------

wrapper.h header file for all wrapper programs

wrapnull.c null wrapper - default install

--------------------------------------------------------------

log.c logging and depth calculation support

log2.c old logging - kept in case

wraplog.c logging wrapper

--------------------------------------------------------------

ACextract cat /dev/wraplog | ACextract > AC.h to build Access Control

AC.c Access Control functions

AC.h Access Control table (autogen with ACextract)

wrapAC.c Access Control wrapper

--------------------------------------------------------------

PLACextract cat /dev/wraplog | ACextract > PLAC.h to build PL Access Control

PL.c Process lineage generation and logging functions

PLAC.c Process Lineage Access Control function

PLAC.h Process Lineage Access Control table (autogen with PLACextract)

wrapPL.c Process Lineage wrapper

wrapPLlog.c Process Lineage logger (for use in making PLAC.h)

--------------------------------------------------------------

wrapSSH.c SSH wrapper for 2-system deception

wrapNPS.c NPS wrapper program (AC + depth limit)

--------------------------------------------------------------

wrapIPC.c IPC wrapper program

--------------------------------------------------------------

Dextract Extract depths from wraplog (cat /root/wraplog | Dextract) for D.h

argcount Counts arguments (echo $#) in support of Dextract

D.c Depth control functions

D.h Depth assignments for pathname, depth pairs

wrapPLACD.c Wrapper combining Process Lineage, Access Control,

and Depth as controls

wrapD.c Wrapper with exact depth as control

--------------------------------------------------------------

NPSwrap.h OLD - not necessary for a present embodiment

stuff.c OLD - not necessary for a present embodiment

# File AC.c

/* Access Control */

#include "AC.h"

/* Runs through list of allowed programs: 1 if 'filename' on list, else 0 */

int ACallowed(char *filename)

{int i;

for (i = 0; ALLOWED[i]; i++) {if (! strncmp(filename, ALLOWED[i], strlen(filename))) return(1);}

if (getpid() < SYSPROCTHRESH) return(1); /* system processes ... we forgive them for now */

return 0;

}

# File ACextract

echo 'char *ALLOWED[] = {'

grep '^/' | sed 's:;: :g' | while read a b; do echo "\"$a\","; done | sort | noreps.pl

echo '"/sbin/init"'

echo '};'

# File AC.h

char *ALLOWED[] = {

"/bin/df",

"/bin/cp",

"/bin/ps",

"/bin/sh",

"/usr/bin/date",

"/usr/bin/du",

"/usr/bin/find",

"/usr/bin/sort",

"/usr/bin/tail",

"/usr/local/bin/me"

};

# File argcount

echo -n $#

# File BACextract

echo "(setq commands (make-hash-table :test 'equal))"

grep '^/' | sed 's:;: :g' | while read a b; do echo "(setf (gethash \"$a\" commands) 'allowed) "; done | sort | noreps.pl

# File D.c

/* Process Lineage Access Control */

#include "D.h"

/* Runs through list of allowed programs: 1 if 'filename' on list, else 0 */

int Dallowed(char *filename)

{int i;

for (i = 0; DALLOWED[i].name; i++)

{if ((DALLOWED[i].depth == depth) &&

(0 == strncmp(filename, DALLOWED[i].name, strlen(filename)))) return(1);}

if (getpid() < SYSPROCTHRESH) return(1); /* system processes... we forgive them for now */

return 0;

}

# File Dextract

grep '^/' | sort | noreps.pl | while read a; do echo "$a"; done | sed 's/;/ /g' | while read a b

do

echo -n "$a "

echo `argcount $b`

done

# File D.h

struct dallow {char *name; int depth;};

struct dallow DALLOWED[9];

void initdallow()

{ DALLOWED[0].name="/bin/df";DALLOWED[0].depth=12;

DALLOWED[1].name="/bin/cp";DALLOWED[1].depth=12;

DALLOWED[2].name="/bin/ps";DALLOWED[2].depth=12;

DALLOWED[3].name="/bin/sh";DALLOWED[3].depth=12;

DALLOWED[4].name="/usr/bin/date";DALLOWED[4].depth=12;

DALLOWED[5].name="/usr/bin/du";DALLOWED[5].depth=12;

DALLOWED[6].name="/usr/bin/find";DALLOWED[6].depth=12;

DALLOWED[7].name="/usr/bin/sort";DALLOWED[7].depth=12;

DALLOWED[8].name="/usr/bin/tail";DALLOWED[8].depth=12;

DALLOWED[9].name="/usr/local/bin/me";DALLOWED[9].depth=12;

}

# File Log2.c

/* Logs the programs that have been run.

* logfile: name of the file to put the log in

* program: name of the program being wrapped

* argc: number of args for program

* argv: argument array for program*/

int log(char *logfile, char *program, int argc, char *argv[])

{

FILE *logfp;

int i, pid;

char pidstr[MAXPIDDIGITS];

logfp = fopen(logfile, "a");

if (! logfp)

{

//printf("Can't open log file\n");

return -1;

}

fputs("\"User's call\",", logfp);

fputs(program, logfp);

fputs("\n\"Args\"", logfp);

for (i = 0; i < argc; i++)

{

fputs(",", logfp);

fputs(argv[i], logfp);

}

pid = getpid();

itoa(pid, pidstr);

log_lineage(logfp, pidstr);

fputs("\n", logfp);

fclose(logfp);

return 1;

}

/*****

* Traces the process lineage of process pid and logs the results in

* file filep. Results are in the form of a .csv file.

**/

void log_lineage(FILE *filep, char *pid)

{

FILE *pstats;

char *statline, *pathname, *ppid, *stat, *label;

pathname = (char *) malloc((strlen(PROC)+strlen(pid)+strlen(STATUS)) * sizeof(char));

if (! pathname)

{

printf("Insufficient memory for logging\n");

return;

}

sprintf(pathname, "%s%s%s", PROC, pid, STATUS);

pstats = fopen(pathname, "r");

if (! pstats)

{

printf("Can't open file %s for reading\n", pathname);

return;

}

free(pathname);

statline = (char *) malloc(MAXLINELEN * sizeof(char));

label = (char *) malloc(MAXLABELLEN * sizeof(char));

stat = (char *) malloc(MAXINFOLEN * sizeof(char));

ppid = (char *) malloc(MAXPIDDIGITS * sizeof(char));

if ((! statline) || (! label) || (! stat) || (! ppid))

{

printf("Insufficient memory for logging\n");

return;

}

fputs("\n\"->\",", filep);

while (fgets(statline, MAXLINELEN, pstats))

{

if (! strncmp(PPID, statline, strlen(PPID)))

{

getlabel(statline, label);

getinfo(statline, ppid);

fputs("\"", filep);

fputs(label, filep);

fputs("\",", filep);

fputs(ppid, filep);

}

else

{

getlabel(statline, label);

getinfo(statline, stat);

fputs("\"", filep);

fputs(label, filep);

fputs("\",", filep);

fputs(stat, filep);

}

fputs("\n", filep);

}

if (strncmp(ppid, ZERO, strlen(ZERO)))

{

log_lineage(filep, ppid);

}

fclose(pstats);

free(statline);

free(stat);

free(label);

free(ppid);

}

/*****

* Extracts the data from a line of the status

* file in proc. Lines are of the form:

* "Label: data"

* procline: a line of the file /proc/(pid)/status

* infobuf: array to put the data in*/

void getinfo(char *procline, char *infobuf)

{

int i, j, getdata, logspaces;

getdata = logspaces = j = 0;

for (i = 0; i < strlen(procline); i++)

{

if (getdata)

{

if (logspaces && (procline[i] != '\n'))

{

infobuf[j] = procline[i];

j++;

}

else if (! isspace(procline[i]))

{

logspaces = 1;

infobuf[j] = procline[i];

j++;

}

}

else if (procline[i] == ':')

{

getdata = 1;

}

}

infobuf[j] = (char) NULL;

}

/*****

* Extracts the label and from a line of the status

* file in proc. Lines are of the form:

* "Label: data"

*

* procline: a line of the file /proc/(pid)/status

* infobuf: array to put the data in*/

int getlabel(char *procline, char *infobuf)

{

int i, getdata;

getdata = i = 0;

while (procline[i] != ':')

{

infobuf[i] = procline[i];

i++;

}

infobuf[i] = (char) NULL;

return i;

}

/* From K&R page 64 (see wrapper.h for details)

* Converts an int n to a string, puts the results in s.*/

void itoa(int n, char s[])

{

int i, sign;

if ((sign = n) < 0)

{

n = -n;

}

i = 0;

do

{

s[i++] = n % 10 + '0';

}

while ((n /= 10) > 0);

if (sign < 0)

{

s[i++] = '-';

}

s[i] = '\0';

reverse(s);

}

/* From K&R page 62 (see wrapper.h for details)

* Reverses the order of the characters in s.*/

void reverse(char s[])

{

int c, i, j;

for (i = 0, j = strlen(s) - 1; i < j; i++, j--)

{

c = s[i];

s[i] = s[j];

s[j] = c;

}

}

# File log.c

#define DEPTH_THRESH 16

int depth;

/* Log the programs that have been run. */

int log(char *logfile, char *program, int argc, char *argv[])

{FILE *logfp;

int i,err, pid;

char pidstr[MAXPIDDIGITS];

logfp = fopen(logfile, "a");

if (! logfp) {return -1;}

fputs("\"User's call\",", logfp);

fputs(program, logfp);

fputs("\n\"Args\"", logfp);

for (i = 0; i < argc; i++) {fputs(",", logfp);fputs(argv[i], logfp);}

pid = getpid();

itoa(pid, pidstr);

if ((err=loglineage(logfp, pidstr)) != 0) fputs("\n", logfp);

fclose(logfp);

return 1;

}

/*****

* Traces the process lineage of process pid and logs the results in

* file filep. Results are in the form of a .csv file.

**/

int loglineage(FILE *filep, char *pid)

{FILE *pstats;

char *statline, *pathname, *ppid, *stat, *label;

pathname = (char *) malloc((strlen(PROC)+strlen(pid)+strlen(STATUS)) * sizeof(char));

if (! pathname) {printf("Insufficient memory for logging\n");return 1;}

sprintf(pathname, "%s%s%s", PROC, pid, STATUS);

pstats = fopen(pathname, "r");

if (! pstats) {printf("Can't open file %s for reading\n", pathname);return 1;}

free(pathname);

statline = (char *) malloc(MAXLINELEN * sizeof(char));

label = (char *) malloc(MAXLABELLEN * sizeof(char));

stat = (char *) malloc(MAXINFOLEN * sizeof(char));

ppid = (char *) malloc(MAXPIDDIGITS * sizeof(char));

if ((! statline) || (! label) || (! stat) || (! ppid))

{printf("Insufficient memory for logging\n");return 1;}

fputs("\n\"->\",", filep);

while (fgets(statline, MAXLINELEN, pstats))

{if (! strncmp(PPID, statline, strlen(PPID)))

{

getlabel(statline, label);

getinfo(statline, ppid);

fputs("\"", filep);

fputs(label, filep);

fputs("\",", filep);

fputs(ppid, filep);}

else {getlabel(statline, label);

getinfo(statline, stat);

fputs("\"", filep);

fputs(label, filep);

fputs("\",", filep);

fputs(stat, filep);}

fputs("\n", filep);

}

if (strncmp(ppid, ZERO, strlen(ZERO))) {depth++;loglineage(filep, ppid);}

fclose(pstats);free(statline);free(stat);free(label);free(ppid);

return(0);

}

/* Extract data from proc */

void getinfo(char *procline, char *infobuf)

{int i, j, getdata, logspaces;

getdata = logspaces = j = 0;

for (i = 0; i < strlen(procline); i++)

{if (getdata)

{if (logspaces && (procline[i] != '\n'))

{infobuf[j] = procline[i];j++;}

else if (! isspace(procline[i]))

{logspaces = 1;

infobuf[j] = procline[i];

j++;

}

}

else if (procline[i] == ':') {getdata = 1;}

}

infobuf[j] = (char) NULL;

}

/* Extracts the label and from a line of the status

* file in proc. Lines are of the form:

* "Label: data"

*

* procline: a line of the file /proc/(pid)/status

* infobuf: array to put the data in*/

int getlabel(char *procline, char *infobuf)

{int i, getdata;

getdata = i = 0;

while (procline[i] != ':') {infobuf[i] = procline[i];i++;}

infobuf[i] = (char) NULL;

return i;

}

/* From K&R page 64 (see wrapper.h for details)

* Converts an int n to a string, puts the results in s. */

void itoa(int n, char s[])

{int i, sign;

if ((sign = n) < 0) {n = -n;}

i = 0;

do {s[i++] = n % 10 + '0';} while ((n /= 10) > 0);

if (sign < 0) {s[i++] = '-';}

s[i] = '\0';

reverse(s);

}

/* From K&R page 62 (see wrapper.h for details)

* Reverses the order of the characters in s. */

void reverse(char s[])

{int c, i, j;

for (i = 0, j = strlen(s) - 1; i < j; i++, j--)

{c = s[i];s[i] = s[j];s[j] = c;}

}

# File Makefile

all: wrapnull wraplog wrapIPC wrapNPS wrapSSH wrapPLlog wrapPL wrapAC \

wrapPLACD wrapD wrapBrain

wrapnull: wrapper.h wrapnull.c

gcc -Wall -o wrapnull wrapnull.c

wraplog: wrapper.h wraplog.c log.c

gcc -Wall -o wraplog wraplog.c

wrapAC: wrapper.h wrapAC.c PL.c AC.c AC.h

gcc -Wall -o wrapAC wrapAC.c

wrapD: wrapper.h wrapD.c PL.c D.c D.h

gcc -Wall -o wrapD wrapD.c

wrapIPC: wrapper.h ../brains/IPCtest.c wrapIPC.c

gcc -Wall -o IPCtest ../brains/IPCtest.c

gcc -Wall -o wrapIPC wrapIPC.c

wrapBrain: wrapper.h ../brains/IPCtest.c wrapBrain.c

gcc -Wall -o wrapBrain wrapBrain.c

cd ../brains; make brain

wrapNPS: NPSwrap.h wrapNPS.c log.c AC.c AC.h

gcc -Wall -o wrapNPS wrapNPS.c

wrapSSH: wrapper.h wrapSSH.c AC.c AC.h

gcc -Wall -o wrapSSH wrapSSH.c

wrapPLlog: wrapper.h wrapPLlog.c PL.c pathname.c

gcc -Wall -o wrapPLlog wrapPLlog.c

wrapPL: wrapper.h wrapPL.c PL.c PLAC.c PLAC.h pathname.c

gcc -Wall -o wrapPL wrapPL.c

wrapPLACD: wrapper.h wrapPLACD.c AC.c PL.c PLAC.c PLAC.h pathname.c

gcc -Wall -o wrapPLACD wrapPLACD.c

clean:

touch *.[ch]

fresh:

rm -f nullwrap logwrap IPCwrap NPSwrap SSHwrap

# File NPSwrap.h

#define WRAPPER "/root/wrap"

#define LOG_FILE "/root/wraplog.csv"

// For tracking process lineage

#define PROC "/proc/"

#define STATUS "/status"

#define MAXPIDDIGITS 10

#define MAXLINELEN 500

#define MAXINFOLEN 100

#define MAXLABELLEN 50

#define PPID "PPid"

#define ZERO "0"

// For the su demo

#define DEMO 0 /* If DEMO = 1, run the su demo */

#define SU "/bin/su"

#define SU_FILE "/tmp/sucount"

#define FAKE_SU "/root/su"

/* Access control variables */

#define DEPTH_THRESH 16

/* Executable names */

/* Access control functions */

int is_allowed(char *filename);

/* Taken from "The C Programming Language" by Kernighan & Ritchie

* Pages 62 and 64 of the second edition*/

# File pathname.c

#define MAXPATHLEN 1024

char pathname[MAXPATHLEN];

int getpathname(char *program)

{int pid;

int pipefd[2];

int waitstat;

if (0 != pipe(pipefd)) {return PIPEERR;}

if (0 != (pid = fork())) /* Parent or failed */

{if (pid < 0) { close(pipefd[0]); close(pipefd[1]); return FORKERR; }

if (waitpid(pid, &waitstat, 0) != pid) {return WAITERR;}

if (WEXITSTATUS(waitstat) == 0)

{read(pipefd[0], &pathname, MAXPATHLEN);close(pipefd[0]); close(pipefd[1]);}

else {close(pipefd[0]); close(pipefd[1]); return GETWDERR;}

}

else { /* Child */

int i;

char dirname[MAXPATHLEN];

close(pipefd[0]);

for (i = strlen(program); i >= 0; i--)

{if (program[i] == '/')

{program[i] = '\0';

if (0 != chdir(program)) { exit(1); }

if (0 == getcwd(dirname, MAXPATHLEN)) { exit(1); }

break;

}

}

if (i == -1) {if (0 == getcwd(dirname, MAXPATHLEN)) { exit(1); }}

strncat(dirname, "/", 1);

strncat(dirname, &(program[i+1]), MAXPATHLEN);

write(pipefd[1], &dirname, strlen(dirname)+1);

close(pipefd[1]);

exit(0);

}

return(0);

}

# File PLAC.c

/* Process Lineage Access Control */

#include "PLAC.h"

/* Runs through list of allowed programs: 1 if 'filename' on list, else 0 */

int PLallowed(char *filename)

{int i;

for (i = 0; PLALLOWED[i]; i++) {if (! strncmp(filename, PLALLOWED[i], strlen(filename))) return(1);}

if (getpid() < SYSPROCTHRESH) return(1); /* system processes... we forgive them for now */

return 0;

}

# File PLACextract

echo 'char *PLALLOWED[] = {'

grep '^/' | sort | noreps.pl | while read a; do echo "\"$a\","; done

echo '"/sbin/init"'

echo '};'

# File PLAC.h

char *PLALLOWED[] = {

"/bin/bash;wrap;xterm;blackbox;xinit;startx;bash;init",

"/bin/cat;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/cat;wrap;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/cat;wrap;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/cat;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/cat;wrap;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/bin/cat;wrap;sh;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/bin/chmod;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/chmod;wrap;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/chmod;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/chown;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/cp;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/cp;wrap;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/cp;wrap;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/df;wrap;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/df;wrap;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/bin/df;wrap;sh;blackbox;xinit;startx;bash;init",

"/bin/df;wrap;sysviuw.pl;blackbox;xinit;startx;bash;init",

"/bin/dircolors;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/egrep;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/grep;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/grep;wrap;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/grep;wrap;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/bin/grep;wrap;ifup;ifup;sh;blackbox;xinit;startx;bash;init",

"/bin/grep;wrap;ifup;sh;blackbox;xinit;startx;bash;init",

"/bin/grep;wrap;sh;blackbox;xinit;startx;bash;init",

"/bin/hostname;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/hostname;wrap;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/bin/hostname;wrap;ifup;sh;blackbox;xinit;startx;bash;init",

"/bin/hostname;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/hostname;wrap;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/bin/id;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/id;wrap;nessus-adduser;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/id;wrap;nessus-mkcert;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/less;wrap;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/ls;wrap;bash;xterm;blackbox;xinit;startx;bash;init",

"/bin/mkdir;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/mkdir;wrap;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/mkdir;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/mkdir;wrap;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/mv;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/mv;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/ps;wrap;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/bin/rm;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/rm;wrap;ifup-post;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/bin/rm;wrap;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/rm;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/sed;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/bin/sed;wrap;ifup-aliases;ifup-aliases;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/bin/sed;wrap;ifup-post;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/bin/sed;wrap;ifup;ifup;sh;blackbox;xinit;startx;bash;init",

"/bin/sed;wrap;nessus-adduser;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/sed;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/sh;wrap;blackbox;xinit;startx;bash;init",

"/bin/sh;wrap;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/bin/sleep;wrap;sh;blackbox;xinit;startx;bash;init",

"/bin/touch;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/bin/tput;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/cdrom/X11R6/bin/mozilla/mozilla-bin;wrap;run-mozilla.sh;init",

"/cdrom/X11R6/bin/mozilla/mozilla-bin;wrap;run-mozilla.sh;sh;blackbox;xinit;startx;bash;init",

"/cdrom/X11R6/bin/mozilla/mozilla;wrap;init",

"/cdrom/X11R6/bin/mozilla/mozilla;wrap;sh;blackbox;xinit;startx;bash;init",

"/etc/sysconfig/network-scripts/ifup-aliases;wrap;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/etc/sysconfig/network-scripts/ifup-post;wrap;sh;blackbox;xinit;startx;bash;init",

"/etc/sysconfig/network-scripts/ifup-routes;wrap;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/sbin/ifconfig;wrap;ifup-aliases;ifup-aliases;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/sbin/ifconfig;wrap;ifup;sh;blackbox;xinit;startx;bash;init",

"/sbin/modprobe;wrap;devfsd;init",

"/sbin/modprobe;wrap;mozilla-bin;run-mozilla.sh;init",

"/sbin/modprobe;wrap;mozilla-bin;run-mozilla.sh;sh;blackbox;xinit;startx;bash;init",

"/tmp/npulse/autorecheck.pl;wrap;start;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/tmp/npulse/etc/start;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/tmp/npulse/miniserv.pl;wrap;start;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/tmp/npulse/mrelayd.pl;wrap;init",

"/usr/X11R6/bin/mozilla/run-mozilla.sh;wrap;init",

"/usr/X11R6/bin/mozilla/run-mozilla.sh;wrap;sh;blackbox;xinit;startx;bash;init",

"/usr/X11R6/bin/xkill;wrap;blackbox;xinit;startx;bash;init",

"/usr/X11R6/bin/xsetroot;wrap;blackbox;xinit;startx;bash;init",

"/usr/X11R6/bin/xterm;wrap;blackbox;xinit;startx;bash;init",

"/usr/X11R6/bin/xterm;wrap;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/basename;wrap;ifup-post;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/basename;wrap;ifup-post;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/basename;wrap;ifup;ifup;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/basename;wrap;ifup;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/basename;wrap;run-mozilla.sh;init",

"/usr/bin/basename;wrap;run-mozilla.sh;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/clear;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/dirname;wrap;mozilla;init",

"/usr/bin/dirname;wrap;mozilla;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/dirname;wrap;run-mozilla.sh;init",

"/usr/bin/dirname;wrap;run-mozilla.sh;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/find;wrap;WGnpulse.sh;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/usr/bin/ipcalc;wrap;ifup;sh;blackbox;xinit;startx;bash;init",

"/usr/bin/kill;wrap;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/usr/bin/netstat;wrap;netviuw.pl;blackbox;xinit;startx;bash;init",

"/usr/bin/perl;wrap;WGnpulse.sh;blackbox;xinit;startx;bash;init",

"/usr/bin/sort;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/usr/bin/stty;wrap;bash;xterm;blackbox;xinit;startx;bash;init",

"/usr/bin/top;wrap;sysviuw.pl;blackbox;xinit;startx;bash;init",

"/usr/bin/uptime;wrap;sysviuw.pl;blackbox;xinit;startx;bash;init",

"/usr/bin/wc;wrap;sh;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/usr/local/bin/DTK.pl;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/WGnpulse.sh;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/awk;wrap;sh;ptadmin.pl;blackbox;xinit;startx;bash;init",

"/usr/local/bin/ghttrack;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/netviuw.pl;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/noreps.pl;wrap;bash;bash;xterm;blackbox;xinit;startx;bash;init",

"/usr/local/bin/ptadmin.pl;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/services.pl;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/sysviuw.pl;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/time.pl;wrap;blackbox;xinit;startx;bash;init",

"/usr/local/bin/which;wrap;run-mozilla.sh;init",

"/usr/local/bin/which;wrap;run-mozilla.sh;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/bin/nessus-w;wrap;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/bin/nmapfe;wrap;blackbox;xinit;startx;bash;init",

"/usr/sectools/bin/openssl;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/sbin/nessus-adduser;wrap;sh;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/sbin/nessus-mkcert;wrap;sh;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/sbin/nessusd;wrap;init",

"/usr/sectools/sbin/nessusd;wrap;nessus-adduser;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/sbin/nessusd;wrap;nessus-adduser;sh;sh;blackbox;xinit;startx;bash;init",

"/usr/sectools/sbin/nessusd;wrap;nessus-mkcert;sh;sh;blackbox;xinit;startx;bash;init",

};

# File PL.c

#include <sys/wait.h>

#include "pathname.c"

#define MAXPLLEN 8192

char lineage[MAXPLLEN]; /* the last retrieved process lineage string */

#define LOGIT(x) logfp=fopen(LOG_FILE, "a");if (logfp) {fputs(x,logfp);fputs(lineage,logfp);fclose(logfp);} else fprintf(stderr,"!%s%s\n",x,lineage);

#define DEPTH_THRESH 16

int depth;

/* Generate process lineage log entry in lineage

* Ignores possibility of '/' in a filename (not permitted by the kernel)

* Ignores issues of SYM links in path */

int pllog(char *program, int argc, char *argv[])

{char pidstr[MAXPIDDIGITS];

int pid,err;

err=0;depth=0;

if (1 == needpathname(program)) err=getpathname(program);

else {strncpy(pathname, program, MAXPATHLEN);}

if (err != 0) return(err);

translate(pathname); /* appends information into lineage for logging */

pid = getpid();itoa(pid, pidstr);

/* add PID to lineage */

//{char tmp[MAXPATHLEN];

// strncpy(tmp,pidstr,8);strncat(tmp, " ", 2);

// strncat(tmp,pathname,MAXPATHLEN-10);strncpy(lineage,tmp,MAXPATHLEN);}

err=log_lineage(pidstr);

if (err == 0) return(1); else return(err);

}

/* Looks for '.' and '..' in the pathname. (or not absolute)

* Returns 1 if it finds some dots and 0 otherwise. */

int needpathname(char *path)

{int i;

if (path[0] != '/') {return(1);}

if (path[0] == '.') {if (((path[1] == '.') && (path[2] == '/')) || (path[1] == '/')) {return 1;}}

for (i = 0; i < strlen(path); i++)

{if ((path[i] == '/') && (path[i+1] == '.'))

{i += 2;

if ((path[i] == '/') || ((path[i] == '.') && (path[i+1] == '/'))) {return 1;}

}

}

return 0;

}

/* Logs 'stat' into lineage, translating nonprintables into \xx

* e.g., "x;y" is logged as "x\3by" */

void translate(char *stat)

{int i, gotbackslash;

char tmpstring[2];

gotbackslash = 0;

for (i = 0; i < strlen(stat); i++)

{if (((int) stat[i] > 126) || ((int) stat[i] < 33) ||

(stat[i] == '\\') || (stat[i] == ';'))

{char asciival[MAXASCII];

if ((stat[i] == '\\') && (! gotbackslash))

{sprintf(asciival, "\\%x", (int) stat[i]);

strncat(lineage, asciival, MAXPATHLEN);gotbackslash = 1;}

else if ((stat[i] == '\\') && (gotbackslash))

{/* Nolog extra backslash */ gotbackslash = 0;}

else {sprintf(asciival, "\\%x", (int) stat[i]);

strncat(lineage, asciival, MAXPATHLEN);}

}

else {tmpstring[0]=stat[i];tmpstring[1]='\0';strncat(lineage, tmpstring, MAXPATHLEN);}

}

}

/* Trace process lineage, results in lineage ad a PATH-like string */

int log_lineage(char *pid)

{FILE *pstats;

char *statline, *pathname, *ppid, *stat, *label;

pathname = (char *) malloc((strlen(PROC)+strlen(pid)+strlen(STATUS)) * sizeof(char));

if (! pathname) {return(NOMEMERR);}

depth++;

sprintf(pathname, "%s%s%s", PROC, pid, STATUS);

pstats = fopen(pathname, "r");

if (! pstats) {return(NOLOGERR);}

free(pathname);

statline = (char *) malloc(MAXLINELEN * sizeof(char));

label = (char *) malloc(MAXLABELLEN * sizeof(char));

stat = (char *) malloc(MAXINFOLEN * sizeof(char));

ppid = (char *) malloc(MAXPIDDIGITS * sizeof(char));

if ((! statline) || (! label) || (! stat) || (! ppid)) {return(NOLOGERR);}

while (fgets(statline, MAXLINELEN, pstats))

{if (! strncmp(PPID, statline, strlen(PPID)))

{getlabel(statline, label);getinfo(statline, ppid);}

else {getlabel(statline, label);getinfo(statline, stat);}

if (! strncmp(NAME, statline, strlen(NAME)))

{strncat(lineage,";",2);translate(stat);}

}

if (strncmp(ppid, ZERO, strlen(ZERO))) {log_lineage(ppid);}

else {strncat(lineage,"\n",2);}

fclose(pstats);

free(statline);free(stat);free(label);free(ppid);

return(0);

}

/* Extract data from status lines in proc of the form: "Label: data" */

void getinfo(char *procline, char *infobuf)

{int i, j, getdata, logspaces;

getdata = logspaces = j = 0;

for (i = 0; i < strlen(procline); i++)

{if (getdata)

{if (logspaces && (procline[i] != '\n'))

{infobuf[j] = procline[i];j++;}

else if (! isspace(procline[i]))

{logspaces = 1;

infobuf[j] = procline[i];

j++;}

}

else if (procline[i] == ':') {getdata = 1;}

}

infobuf[j] = (char) NULL;

}

/* Extract label from status file in proc of the form: "Label: data" */

int getlabel(char *procline, char *infobuf)

{int i, getdata;

getdata = i = 0;

while (procline[i] != ':') {infobuf[i] = procline[i];i++;}

infobuf[i] = (char) NULL;

return i;

}

/* From K&R page 64: int to string, results in s. */

void itoa(int n, char s[])

{int i, sign;

if ((sign = n) < 0) {n = -n;}

i = 0;

do {s[i++] = n % 10 + '0';} while ((n /= 10) > 0);

if (sign < 0) {s[i++] = '-';}

s[i] = '\0';

reverse(s);

}

/* From K&R page 62: Reverse order of characters in s. */

void reverse(char s[])

{int c, i, j;

for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {c = s[i];s[i] = s[j];s[j] = c;}

}

# File stuff.c

/*****

* Logs the programs that have been run.

*

* logfile: name of the file to put the log in

* program: name of the program being wrapped

* argc: number of args for program

* argv: argument array for program*/

int log(char *logfile, char *program, int argc, char *argv[]) {

FILE *logfp;

int i, pid;

char *pidstr;

logfp = fopen(logfile, "a");

if (! logfp) {

//printf("Can't open log file\n");

//fclose(logfp);

return -1;

}

fputs("\"User's call\",", logfp);

fputs(program, logfp);

fputs("\n\"Args\"", logfp);

for (i = 0; i < argc; i++) {

fputs(",", logfp);

fputs(argv[i], logfp);

}

pid = getpid();

pidstr = (char *) malloc(sizeof(char) * MAXPIDDIGITS);

itoa(pid, pidstr);

log_lineage(logfp, pidstr);

fputs("\n", logfp);

fclose(logfp);

return 1;

}

/*****

* Traces the process lineage of process pid and logs the results in

* file filep. Results are in the form of a .csv file.

**/

void log_lineage(FILE *filep, char *pid) {

FILE *pstats;

char *statline, *proc, *pathname, *ppid, *stat, *label;

proc = (char *) malloc((strlen(PROC)+strlen(pid))*sizeof(char));

strncpy(proc, PROC, strlen(PROC));

proc = strncat(proc, pid, strlen(pid));

pathname = (char *) malloc((strlen(proc) + strlen(STATUS)) * sizeof(char));

strncpy(pathname, proc, strlen(proc));

pathname = strncat(pathname, STATUS, strlen(STATUS));

pstats = fopen(pathname, "r");

if (! pstats) {

printf("Can't open file %s for reading\n", pathname);

//fclose(pstats);

return;

}

statline = (char *) malloc(MAXLINELEN * sizeof(char));

label = (char *) malloc(MAXLABELLEN * sizeof(char));

stat = (char *) malloc(MAXINFOLEN * sizeof(char));

fputs("\n\"->\",", filep);

while (fgets(statline, MAXLINELEN, pstats)) {

if (! strncmp(PPID, statline, strlen(PPID))) {

ppid = (char *) malloc(MAXPIDDIGITS * sizeof(char));

getlabel(statline, label);

getinfo(statline, ppid);

fputs("\"", filep);

fputs(label, filep);

fputs("\",", filep);

fputs(ppid, filep);

}

else {

getlabel(statline, label);

getinfo(statline, stat);

fputs("\"", filep);

fputs(label, filep);

fputs("\",", filep);

fputs(stat, filep);

}

fputs("\n", filep);

}

#ifdef DEPTH

if (strncmp(ppid, ZERO, strlen(ZERO))) {depth++;log_lineage(filep, ppid);}

#elsif

if (strncmp(ppid, ZERO, strlen(ZERO))) {log_lineage(filep, ppid);}

#endif

fclose(pstats);

free(statline);

free(pathname);

free(proc);

free(stat);

free(ppid);

}

/*****

* Extracts the data from a line of the status

* file in proc. Lines are of the form:

* "Label: data"

*

* procline: a line of the file /proc/(pid)/status

* infobuf: array to put the data in*/

void getinfo(char *procline, char *infobuf) {

int i, j, getdata, logspaces;

getdata = logspaces = j = 0;

for (i = 0; i < strlen(procline); i++) {

if (getdata) {

if (logspaces && (procline[i] != '\n')) {

infobuf[j] = procline[i];

j++;

}

else if (! isspace(procline[i])) {

logspaces = 1;

infobuf[j] = procline[i];

j++;

}

}

else if (procline[i] == ':') {

getdata = 1;

}

}

infobuf[j] = (char) NULL;

}

/*****

* Extracts the label and from a line of the status

* file in proc. Lines are of the form:

* "Label: data"

*

* procline: a line of the file /proc/(pid)/status

* infobuf: array to put the data in*/

void getlabel(char *procline, char *infobuf) {

int i, getdata, logspaces;

getdata = logspaces = i = 0;

while (procline[i] != ':') {

infobuf[i] = procline[i];

i++;

}

infobuf[i] = (char) NULL;

}

/* From K&R page 64 (see wrapper.h for details)

* Converts an int n to a string, puts the results in s.*/

void itoa(int n, char s[]) {

int i, sign;

if ((sign = n) < 0) {

n = -n;

}

i = 0;

do {

s[i++] = n % 10 + '0';

} while ((n /= 10) > 0);

if (sign < 0) {

s[i++] = '-';

}

s[i] = '\0';

reverse(s);

}

/* From K&R page 62 (see wrapper.h for details)

* Reverses the order of the characters in s.*/

void reverse(char s[]) {

int c, i, j;

for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {

c = s[i];

s[i] = s[j];

s[j] = c;

}

}

/*****

* Keeps track of how many times "su" has been called in a row.*/

int process_su(char *command, char *argv[], char *envp[]) {

FILE *sufp;

int count;

sufp = fopen(SU_FILE, "r");

if (! sufp) {

fclose(sufp);

sufp = fopen(SU_FILE, "w");

if (! sufp) {

printf("Can't create file\n");

fclose(sufp);

return -1;

}

system("chmod 777 /tmp/sucount"); //change this later

putc(1, sufp);

fclose(sufp);

}

else {

count = getc(sufp);

fclose(sufp);

if (count == EOF || count < 0) {

printf("Invalid file\n");

return -1;

}

if (count >= 3) {

//execve(command, argv, envp);

return 3;

}

else {

count++;

sufp = fopen(SU_FILE, "w");

if (! sufp) {

printf("Can't open for writing\n");

fclose(sufp);

return -1;

}

putc(count, sufp);

fclose(sufp);

}

}

return 1;

}

/*****

* Resets the "su" count to 0.*/

void reset_count() {

FILE *fp;

fp = fopen(SU_FILE, "w");

if (fp) {

putc(0, fp);

}

fclose(fp);

}

# File wrapAC.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "AC.c"

#include "log.c"

/* Argv: arguments to the original call & the original filename

Envp: environment strings from the original call */

int main(int argc, char *argv[], char *envp[])

{char * filename;

// Strip the original filename from the args array

argc -= 1;

filename = argv[argc];

argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

depth = 1;

log(LOG_FILE, filename, argc, argv);

if (1 == ACallowed(filename))

{err = execve(filename, argv, envp);}

else {exit(1);}

perror("DTK");

fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);fflush(stdout);

return(-errno);

}

return -1;

}

# File wrapBrain.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include<sys/ipc.h>

#include<sys/msg.h>

#include<sys/types.h>

#include<signal.h>

#include "wrapper.h"

#define _MSG_SIZE_ 255

struct msgbuf

{

int mtype;

int32_t opcode;

char mtext[_MSG_SIZE_];

};

int32_t qid=-1;

struct msgbuf qmsg;

/*****

* Argv: arguments to the original call & the original filename

* Envp: environment strings from the original call */

int main(int argc, char *argv[], char *envp[])

{char * filename;

// Strip the original filename from the args array

argc -= 1;

filename = argv[argc];

argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else

{

int err;

qid=msgget((key_t) (12345), 0);

if(qid==-1) return(-1);

qmsg.mtype=1;

sprintf(qmsg.mtext, "%d %s", getppid(), filename);

qmsg.opcode=getpid();

if(msgsnd(qid, &qmsg, sizeof(struct msgbuf),IPC_NOWAIT)==-1)

{perror("bad send");return -1;}

msgrcv(qid, &qmsg, sizeof(struct msgbuf), getpid(), 0);

if (qmsg.opcode == 0) {

//execute the program

err = execve(filename, argv, envp);

} else if ((qmsg.opcode < 0) && (qmsg.opcode >= -255)) {

//print string

fprintf(stderr, "%s\n", qmsg.mtext);

return qmsg.opcode;

} else if (qmsg.opcode<-256) {

//bounce to another server, and run the program there

char* newargv[1024];

char s[1024];

sprintf(s, "cd ");

getcwd(s+3, 1020);

strcat(s, ";");

for(qid=0;qid<argc;qid++)

{strcat(s, " ");strcat(s, argv[qid]);}

newargv[0]="ssh";

newargv[1]=qmsg.mtext;

newargv[2]=s;

newargv[3]=NULL;

err = execve("/usr/local/bin/ssh", newargv, envp);

} else if (qmsg.opcode == 255) {

//kill, kill, KILL!!!

kill(getppid(), SIGTERM);

}

perror("Exec Failed");

fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);

fflush(stdout);

printf("exiting:%d\n", -errno);

return(-errno);

}

printf("Houston, we have a problem!\n");

return -1;

}

# File wrapD.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "PL.c"

#include "D.c"

/* Argv: arguments to the original call & the original filename */

int main(int argc, char *argv[], char *envp[])

{char *filename;

FILE *logfp;

// Strip the original filename from the args array

argc -= 1;filename = argv[argc];argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

err = pllog(filename, argc, argv);

switch (err)

{case 1: case 0: {if (Dallowed(pathname) == 1) err = execve(filename, argv, envp);

LOGIT("-X-");perror("Exec failed");

// fprintf(stderr, "error: %d,%d '%s'\n", err, errno, filename);

fflush(stderr);fflush(stdout);return(-errno);}

case FORKERR: {LOGIT("-F-");printf("%s\n", FORKERRMSG);exit(1);}

case FDERR: {LOGIT("-D-");printf("%s\n", FDERRMSG);exit(1);}

case PIPEERR: {LOGIT("-P-");printf("%s\n", PIPEERRMSG);exit(1);}

case WAITERR: {LOGIT("-S-");printf("%s\n", WAITERRMSG);exit(1);}

case GETWDERR: {LOGIT("-W-");printf("%s\n", GETWDERRMSG);exit(1);}

case NOLOGERR: {LOGIT("-L-");if (getpid() < SYSPROCTHRESH) {err = execve(filename, argv, envp);}

printf("%s\n", NOLOGERRMSG);exit(1);}

case NOMEMERR: {LOGIT("-M-");printf("%s\n", NOMEMERRMSG);exit(1);}

default: {LOGIT("-O-");printf("Process Error %d\n", err);perror("Ouch!!!");exit(1);}

}

}

return -1;

}

# File wrapIPC.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include<sys/ipc.h>

#include<sys/msg.h>

#include "wrapper.h"

#define _MSG_SIZE_ 255

struct msgbuf

{

int mtype;

int32_t opcode;

char mtext[_MSG_SIZE_];

};

int32_t qid=-1;

//memcpy(qmsg.mtext, "Hello World", _MSG_SIZE_);

sprintf(qmsg.mtext, "%d %s", getppid(), filename);

qmsg.opcode=getpid();

//printf("Sending");

if(msgsnd(qid, &qmsg, sizeof(struct msgbuf),IPC_NOWAIT)==-1)

{perror("bad send");return -1;}

//{perror("bad send");return(-1);}

//printf("Recving");

msgrcv(qid, &qmsg, sizeof(struct msgbuf), getpid(), 0);

// printf("%d %d %s", qmsg.mtype, qmsg.opcode, qmsg.mtext);

if(qmsg.opcode<0)

{

fprintf(stderr, "%s\n", qmsg.mtext);

return -qmsg.opcode;

}

else if(qmsg.opcode>0)

{

char* newargv[1024];

char s[1024];

switch(qmsg.opcode)

{

case 1 :

//--help

break;

case 2 :

//--help

break;

case 3 :

//ssh

sprintf(s, "cd ");

getcwd(s+3, 1020);

strcat(s, ";");

for(qid=0;qid<argc;qid++)

{strcat(s, " ");strcat(s, argv[qid]);}

newargv[0]="ssh";

//newargv[1]="10.0.0.123";

newargv[1]=qmsg.mtext;

newargv[2]=s;

newargv[3]=NULL;

err = execve("/usr/local/bin/ssh", newargv, envp);

break;

case 4 :

//blahblahblah

break;

//...

case 42 :

err = execve(filename, argv, envp);

break;

default :

return -1;

}

}

else

err = execve(filename, argv, envp);

//printf("Execing");

perror("Exec Failed");

fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);

fflush(stdout);

printf("exiting:%d\n", -errno);

return(-errno);

}

printf("Houston, we have a problem!\n");

return -1;

}

# File wraplog.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "log.c"

/* Argv: arguments to the original call & the original filename */

int main(int argc, char *argv[], char *envp[])

{char * filename;

argc -= 1;filename = argv[argc];argv[argc] = NULL; // Strip the original filename from the args array

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

log(LOG_FILE, filename, argc, argv);

err = execve(filename, argv, envp);

perror("Exec failed");

fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);fflush(stdout);

printf("exiting:%d\n", -errno);

return(-errno);

}

return -1;

}

# File wrapNPS.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "AC.c"

#include "log.c"

/* Argv: arguments to the original call & the original filename

Envp: environment strings from the original call */

int main(int argc, char *argv[], char *envp[])

{char * filename;

// Strip the original filename from the args array

argc -= 1;

filename = argv[argc];

argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

depth = 1;

log(LOG_FILE, filename, argc, argv);

if ((depth <= DEPTH_THRESH) && (1 == ACallowed(filename)))

{err = execve(filename, argv, envp);}

else {exit(1);}

perror("DTK");

fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);fflush(stdout);

return(-errno);

}

return -1;

}

# File wrapnull.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

/* Argv: arguments to the original call & the original filename */

int main(int argc, char *argv[], char *envp[])

{char * filename;

// Strip the original filename from the args array

argc -= 1;filename = argv[argc];argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");exit(0);}

else {int err;

err = execve(filename, argv, envp);

perror("Exec failed");

// fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);fflush(stdout);

// printf("exiting:%d\n", -errno);return(-errno);

}

exit(1);

}

# File wrapper.h

#define WRAPPER "/root/wrap"

#define LOG_FILE "/root/wraplog"

#define VERBOSE 1

#define DEBUG 1

#define SYSPROCTHRESH 100

/* system process ID threshold */

// For tracking process lineage

#define PROC "/proc/"

#define STATUS "/status"

#define MAXPIDDIGITS 5

#define MAXLINELEN 500

#define MAXINFOLEN 100

#define MAXLABELLEN 10

#define MAXASCII 2048

#define PPID "PPid"

#define NAME "Name"

#define ZERO "0"

#define FORKERR -24

#define FORKERRMSG "Fork failed"

#define FDERR -25

#define FDERRMSG "Invalid file descriptor"

#define PIPEERR -26

#define PIPEERRMSG "Pipe failed"

#define WAITERR -27

#define WAITERRMSG "Process zombie"

#define GETWDERR -28

#define GETWDERRMSG "Invalid working directory"

#define NOLOGERR -29

#define NOLOGERRMSG "No log file"

#define NOMEMERR -30

#define NOMEMERRMSG "Out of memory"

// For the su demo

#define DEMO 0 /* If DEMO = 1, run the su demo */

#define SU "/bin/su"

#define SU_FILE "/tmp/sucount"

#define FAKE_SU "/root/su"

/* Logging functions */

int log(char *logfile, char *program, int argc, char *argv[]); /* Direct to file logging */

int pllog(char *program, int argc, char *argv[]); /* process lineage logline generation */

int needpathname(char *path); /* Do I need a pathname? */

void translate(char *stat); /* Change all characters to printable representations */

int log_lineage(char *pid); /* short form lineage logging */

int loglineage(FILE *filep, char *pid); /* long form lineage logging direct to file for log.c only */

void getinfo(char *procline, char *infobuf);

int getlabel(char *procline, char *infobuf);

void itoa(int n, char s[]);

void reverse(char s[]);

/* Functions for a dead demo */

int process_su(char *command, char *argv[], char *envp[]);

void reset_count();

# File wrapPLACD.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "PLAC.c"

#include "PL.c"

#include "AC.c"

/* Argv: arguments to the original call & the original filename */

int main(int argc, char *argv[], char *envp[])

{FILE *logfp;

char * filename; // Strip the original filename from the args array

argc -= 1;filename = argv[argc];argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

err = pllog(filename, argc, argv);

switch (err)

{case 1: case 0: {if (((1 == PLallowed(lineage)) || (1 == ACallowed(filename))) && (depth < DEPTH_THRESH))

{LOGIT("");

err = execve(filename, argv, envp);

LOGIT("-X-");

perror("Exec failed");

// fprintf(stderr, "error: %d,%d '%s'\n", err, errno, filename);

fflush(stderr);fflush(stdout);return(-errno);}

else {LOGIT("-A-");fprintf(stderr,"%s\n", FORKERRMSG);exit(-1);}

}

case FORKERR: {LOGIT("-F-");printf("%s\n", FORKERRMSG);exit(1);}

case FDERR: {LOGIT("-D-");printf("%s\n", FDERRMSG);exit(1);}

case PIPEERR: {LOGIT("-P-");printf("%s\n", PIPEERRMSG);exit(1);}

case WAITERR: {LOGIT("-S-");printf("%s\n", WAITERRMSG);exit(1);}

case GETWDERR: {LOGIT("-W-");printf("%s\n", GETWDERRMSG);exit(1);}

case NOLOGERR: {LOGIT("-L-");if (getpid() < SYSPROCTHRESH) {err = execve(filename, argv, envp);}

printf("%s\n", NOLOGERRMSG);exit(1);}

case NOMEMERR: {LOGIT("-M-");printf("%s\n", NOMEMERRMSG);exit(1);}

default: {LOGIT("-O-");printf("Process Error %d\n", err);perror("Ouch!!!");exit(1);}

}

}

return -1;

}

# File wrapPL.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "PLAC.c"

#include "PL.c"

/* Argv: arguments to the original call & the original filename */

int main(int argc, char *argv[], char *envp[])

{FILE *logfp;

char * filename; // Strip the original filename from the args array

argc -= 1;filename = argv[argc];argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

err = pllog(filename, argc, argv);

switch (err)

{case 1: case 0: {if (1 == PLallowed(lineage))

{LOGIT("");

err = execve(filename, argv, envp);

LOGIT("-X-");

perror("Exec failed");

// fprintf(stderr, "error: %d,%d '%s'\n", err, errno, filename);

fflush(stderr);fflush(stdout);return(-errno);}

else {LOGIT("-A-");fprintf(stderr,"%s\n", FORKERRMSG);exit(-1);}

}

case FORKERR: {LOGIT("-F-");printf("%s\n", FORKERRMSG);exit(1);}

case FDERR: {LOGIT("-D-");printf("%s\n", FDERRMSG);exit(1);}

case PIPEERR: {LOGIT("-P-");printf("%s\n", PIPEERRMSG);exit(1);}

case WAITERR: {LOGIT("-S-");printf("%s\n", WAITERRMSG);exit(1);}

case GETWDERR: {LOGIT("-W-");printf("%s\n", GETWDERRMSG);exit(1);}

case NOLOGERR: {LOGIT("-L-");if (getpid() < SYSPROCTHRESH) {err = execve(filename, argv, envp);}

printf("%s\n", NOLOGERRMSG);exit(1);}

case NOMEMERR: {LOGIT("-M-");printf("%s\n", NOMEMERRMSG);exit(1);}

default: {LOGIT("-O-");printf("Process Error %d\n", err);perror("Ouch!!!");exit(1);}

}

}

return -1;

}

# File wrapPLlog.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "PL.c"

/* Argv: arguments to the original call & the original filename */

int main(int argc, char *argv[], char *envp[])

{char *filename;

FILE *logfp;

// Strip the original filename from the args array

argc -= 1;filename = argv[argc];argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else {int err;

err = pllog(filename, argc, argv);

switch (err)

{case 1: case 0: {LOGIT("");err = execve(filename, argv, envp);

LOGIT("-X-");perror("Exec failed");

// fprintf(stderr, "error: %d,%d '%s'\n", err, errno, filename);

fflush(stderr);fflush(stdout);return(-errno);}

case FORKERR: {LOGIT("-F-");fprintf(stderr, "%s\n", FORKERRMSG);exit(1);}

case FDERR: {LOGIT("-D-");fprintf(stderr, "%s\n", FDERRMSG);exit(1);}

case PIPEERR: {LOGIT("-P-");fprintf(stderr, "%s\n", PIPEERRMSG);exit(1);}

case WAITERR: {LOGIT("-S-");fprintf(stderr, "%s\n", WAITERRMSG);exit(1);}

case GETWDERR: {LOGIT("-W-");fprintf(stderr, "%s\n", GETWDERRMSG);exit(1);}

case NOLOGERR: {LOGIT("-L-");err = execve(filename, argv, envp);

printf("%s\n", NOLOGERRMSG);exit(1);}

case NOMEMERR: {LOGIT("-M-");fprintf(stderr, "%s\n", NOMEMERRMSG);exit(1);}

default: {LOGIT("-O-");fprintf(stderr, "Process Error %d\n", err);perror("Ouch!!!");exit(1);}

}

}

return -1;

}

# File wrapSSH.c

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <syscall.h>

#include <stdlib.h>

#include <ctype.h>

#include <errno.h>

#include "wrapper.h"

#include "AC.c"

#include "PL.c"

/*****

* Argv: arguments to the original call & the original filename

* Envp: environment strings from the original call

*/

int main(int argc, char *argv[], char *envp[])

{char * filename;

char* newargv[1024];

char s[1024];

int i;

// Strip the original filename from the args array

argc -= 1;

filename = argv[argc];

argv[argc] = NULL;

// Wrapping the wrapper could lead to an infinite loop

if (! strncmp(filename, WRAPPER, strlen(WRAPPER))) {printf("Wrapping error\n");}

else if (1 == ACallowed(filename))

{int err;err = execve(filename, argv, envp);

perror("Exec failed");

fprintf(stderr, "error: %d,%d\n", err, errno);

fflush(stderr);fflush(stdout);

printf("exiting:%d\n", -errno);return(-errno);

}

else {int err;

pllog(filename, argc, argv);

sprintf(s, "cd ");

getcwd(s+3, 1010);

strcat(s, ";");

for(i=0;i<argc;i++) {strcat(s, " ");strcat(s, argv[i]);}

newargv[0]="/usr/local/bin/ssh";

newargv[1]="10.0.0.123";

newargv[2]=s;

newargv[3]=NULL;

err = execve("/usr/local/bin/ssh", newargv, envp);

}

perror("DTK");

return(-errno);

return -1;

}

Example Kernel changes

[0004] The following series of 'diff' output describes an example of code changes made to a Linux 2.4.18 kernel in order to implement a wrapper according to specific embodiments of the present invention and also to implement other operating system modifications for deception. Lines starting with '# diff' indicate first the name of the new kernel file and which code lines are deleted or added from the original kernel file. This code could be used with a patch command or program in Linux to automatically modify the indicated files as will be understood to persons of skill in the art.


Program changes for wrapper include files:

exec.c, sched.h, process.c, entry.S

Program changes for the module include:

ksyms.c, user.c, dnotify.c

# diff exec.c /u/usr/src/linux-2.4.18/fs/exec.c

45,53d44

< #include <asm/ptrace.h> // need to access pt_regs fields

< #include <linux/sched.h> // need WRAP_FLAG, WRAP_PATH

< #include <linux/elf.h> // For rec_elf_binary()

< #define DEBUGGING 0 // print debugging statements

< #define DEBUG_MEM 0

58,77d48

< // For rec_misc_binary() (taken from binfmt_misc.c)

< typedef struct {

< struct list_head list;

< int flags; /* type, status, etc. */

< int offset; /* offset of magic */

< int size; /* size of magic/mask */

< char *magic; /* magic or filename extension */

< char *mask; /* mask, NULL for exact match */

< char *interpreter; /* filename of interpreter */

< char *name;

< struct dentry *dentry;

< } Node;

< static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;

< enum {Enabled, Magic};

< static LIST_HEAD(entries);

83,114d53

< /*sys_ad -- checks if a certain pid is the actual wrapper process.

< the wrapper process has a flag set in the flags field of the task_struct.

< the flag is defined as WRAP_FLAG in linux/sched.h.

< */

< /*** DTK(dcvn)--- start ***/

< asmlinkage long sys_ad(int pid){

< struct task_struct *p;

< if(current->uid) { //if not root, return original error

< //printk(KERN_CRIT "sys_ad1\n");

< return -ENOSYS;

< }

< p=find_task_by_pid(pid);

< if(p==NULL) { //if no such pid, return standard error

< //printk(KERN_CRIT "sys_ad2\n");

< return -ENOSYS;

< }

< if(p->flags&WRAP_FLAG){ //if it's the wrapper return different error

< //printk(KERN_CRIT "sys_ad3\n");

< return -EAGAIN;

< }

< //printk(KERN_CRIT "sys_ad4\n");

< return -ENOSYS; // otherwise return original error

< }

< /*** DTK(dcvn)--- end ***/

221a161

226c166

< if (get_user(p, argv)) {

---

> if (get_user(p, argv))

228,229c168

< }

< if (!p) {

---

> if (!p)

231d169

< }

233c171

< if(++i > max) {

---

> if(++i > max)

235d172

< }

253,254c190

< if (get_user(str, argv+argc) || !(len = strnlen_user(str, bprm->p))) {

< printk(KERN_CRIT "copy_strings 1\n");

---

> if (get_user(str, argv+argc) || !(len = strnlen_user(str, bprm->p)))

256d191

< }

279d213

< if (DEBUG_MEM) printk("page allocated from copy_strings (%s)\n", bprm->file->f_dentry->d_name.name);

295,296c229

< if (err) {

< printk(KERN_CRIT "copy_strings 2\n");

---

> if (err)

298d230

< }

414,416c346

< if (DEBUGGING) printk(KERN_CRIT "open_exec(%s)\n", name);

< if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd)) {

---

> if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))

418,419d347

< }

421d348

427,428c354

< int err = permission(inode, MAY_EXEC);

---

> int err = permission(inode, MAY_EXEC);

432d357

434d358

< if (DEBUG_MEM) printk(KERN_CRIT "%s: about to dentry_open from open_exec\n", name);

842d765

886c809

< continue;

---

> continue;

929,1115d851

< /* DTK: The rec_xxx_binary() methods return 1 if the binary format is

< * recognized and 0 otherwise. The checks are taken directly from the

< * load_xxx_binary() methods defined in fs/binfmt_xxx.c.

< */

< int rec_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) {

< struct exec ex;

< ex = *((struct exec *) bprm->buf); /* exec-header */

< if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&

< N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||

< N_TRSIZE(ex) || N_DRSIZE(ex) ||

< bprm->file->f_dentry->d_inode->i_size <

< ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {

< return -ENOEXEC;

< }

< else { return 1; }

< }

< int rec_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) {

< struct elfhdr elf_ex;

< elf_ex = *((struct elfhdr *) bprm->buf);

< if ( (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0) ||

< (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||

< (!elf_check_arch(&elf_ex)) ||

< (!bprm->file->f_op||!bprm->file->f_op->mmap) ) {

< return -ENOEXEC;

< }

< else {

< return 1;

< }

< }

< static Node *check_file(struct linux_binprm *bprm)

< {

< char *p = strrchr(bprm->filename, '.');

< struct list_head *l;

< for (l = entries.next; l != &entries; l = l->next) {

< Node *e = list_entry(l, Node, list);

< char *s;

< int j;

< if (!test_bit(Enabled, &e->flags))

< continue;

< if (!test_bit(Magic, &e->flags)) {

< if (p && !strcmp(e->magic, p + 1))

< return e;

< continue;

< }

< s = bprm->buf + e->offset;

< if (e->mask) {

< for (j = 0; j < e->size; j++)

< if ((*s++ ^ e->magic[j]) & e->mask[j])

< break;

< } else {

< for (j = 0; j < e->size; j++)

< if ((*s++ ^ e->magic[j]))

< break;

< }

< if (j == e->size)

< return e;

< }

< return NULL;

< }

< int rec_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) {

< Node *fmt;

< char iname[BINPRM_BUF_SIZE];

< read_lock(&entries_lock);

< fmt = check_file(bprm);

< if (fmt) {

< strncpy(iname, fmt->interpreter, BINPRM_BUF_SIZE - 1);

< iname[BINPRM_BUF_SIZE - 1] = '\0';

< }

< read_unlock(&entries_lock);

< if (!fmt) { return -ENOEXEC; }

< else { return 1; }

< }

< int rec_script_binary(struct linux_binprm *bprm, struct pt_regs *regs) {

< char *cp, *i_name, *i_arg;

< struct file *file;

< char interp[BINPRM_BUF_SIZE];

< int retval;

< if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang)) {

< if (DEBUGGING) printk(KERN_CRIT "#! not recognized\n");

< return -ENOEXEC;

< }

< // DTK: Now make sure the specified interpreter can be executed

< bprm->sh_bang++;

< bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';

< if ((cp = strchr(bprm->buf, '\n')) == NULL)

< cp = bprm->buf+BINPRM_BUF_SIZE-1;

< *cp = '\0';

< while (cp > bprm->buf) {

< cp--;

< if ((*cp == ' ') || (*cp == '\t'))

< *cp = '\0';

< else

< break;

< }

< for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);

< if (*cp == '\0')

< return -ENOEXEC; /* No interpreter name found */

< i_name = cp;

< i_arg = 0;

< for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++)

< /* nothing */ ;

< while ((*cp == ' ') || (*cp == '\t'))

< *cp++ = '\0';

< if (*cp)

< i_arg = cp;

< strcpy (interp, i_name);

< if (DEBUGGING) printk(KERN_CRIT "interp:%s\n", interp);

< /*< * OK, we've parsed out the interpreter name and

< * (optional) argument.

< * Splice in (1) the interpreter's name for argv[0]

< * (2) (optional) argument to interpreter

< * (3) filename of shell script (replace argv[0])

< * This is done in reverse order, because of how the

< * user environment and arguments are stored.

< */

< remove_arg_zero(bprm);

< retval = copy_strings_kernel(1, &bprm->filename, bprm);

< if (retval < 0) return retval;

< bprm->argc++;

< if (i_arg) {

< retval = copy_strings_kernel(1, &i_arg, bprm);

< if (retval < 0) return retval;

< bprm->argc++;

< }

< retval = copy_strings_kernel(1, &i_name, bprm);

< if (retval) return retval;

< bprm->argc++;

< /*< * OK, now restart the process with the interpreter's dentry.

< */

< file = open_exec(interp);

< if (! file)

< printk(KERN_CRIT "file is NULL\n");

< if (IS_ERR(file)) {

< return PTR_ERR(file);

< }

< bprm->file = file;

< retval = prepare_binprm(bprm);

< if (retval < 0)

< goto out;

< // Specified interpreter is executable

< retval = 1;

< out:

< if (file) {

< allow_write_access(file);

< fput(file);

< }

< return retval;

< }

1119,1123d854

< * DTK:

< * The EXEC_CKD flag keeps track of the recursion-

< * - EXEC_CKD on: filename has been checked for exec errors and has none

< * - EXEC_CKD off: filename has not been checked for exec errors yet

1129c860

< int retval, retval_aout, retval_elf, retval_misc, retval_script;

---

> int retval;

1131d861

< char * orig_filename;

1133,1141d862

< if (DEBUGGING) printk(KERN_CRIT "do_execve(%s)\n", filename);

< orig_filename = filename;

< if ( (current->flags & EXEC_CKD) && (current->flags & WRAP_FLAG) ) {

< filename = WRAP_PATH;

< }

1143d863

< retval = PTR_ERR(file);

1145c865,866

< if (IS_ERR(file))

---

> retval = PTR_ERR(file);

> if (IS_ERR(file))

1157,1162c878,879

< if (file) {

< allow_write_access(file);

< fput(file);

< }

---

> allow_write_access(file);

> fput(file);

1167,1172c884,885

< if (file) {

< allow_write_access(file);

< fput(file);

< }

---

> allow_write_access(file);

> fput(file);

1174a888

1176,1177c890,891

< if (retval < 0)

< goto out;

---

> if (retval < 0)

> goto out;

1188,1271c902,904

< // If this is the wrapper, add filename of user's original call to the end of argv

< if ((current->flags & WRAP_FLAG) && (current->flags & EXEC_CKD)) {

< char ** newArgv;

< int j;

< newArgv = (char **) kmalloc(sizeof(char *) * (bprm.argc + 2), GFP_KERNEL);

< if (DEBUG_MEM) printk("kmalloc'ing from do_execve(%s)\n", filename);

< if (! newArgv) {

< retval = -ENOMEM;

< goto out;

< }

< for (j = 0; j < bprm.argc; j++) { newArgv[j] = argv[j]; }

< newArgv[j] = orig_filename;

< newArgv[j+1] = NULL;

< bprm.argc++;

< //(char *) (*regs).ebx = filename;

< //(char **) (*regs).ecx = newArgv;

< retval = copy_strings_kernel(bprm.argc, newArgv, &bprm);

< kfree(newArgv);

< if (DEBUG_MEM) printk("kfree'ed from do_execve(%s)\n", filename);

< }

< else {

< retval = copy_strings(bprm.argc, argv, &bprm);

< }

< if (retval < 0) {

< goto out;

< }

< if ( (! (current->flags & EXEC_CKD)) && (current->flags & WRAP_FLAG) ) {

< // Don't run wrapper if we don't recognize the executable format

< retval_aout = rec_aout_binary(&bprm, regs);

< retval_elf = rec_elf_binary(&bprm, regs);

< retval_misc = rec_misc_binary(&bprm, regs);

< retval_script = rec_script_binary(&bprm, regs);

< if ((retval_aout < 0) && (retval_aout != -ENOEXEC)) {

< retval = retval_aout;

< goto out;

< }

< if ((retval_elf < 0) && (retval_elf != -ENOEXEC)) {

< retval = retval_elf;

< goto out;

< }

< if ((retval_misc < 0) && (retval_misc != -ENOEXEC)) {

< retval = retval_misc;

< goto out;

< }

< if ((retval_script < 0) && (retval_script != -ENOEXEC)) {

< retval = retval_script;

< goto out;

< }

< if ((retval_aout < 0) && (retval_elf < 0) && (retval_misc < 0) &&

< (retval_script < 0)) {

< if (DEBUGGING) printk(KERN_CRIT "Executable type not recognized (%s)\n", filename);

< current->flags |= EXEC_CKD;

< }

< }

< // DTK: No exec errors.. Now we can call the wrapper

< if ( (! (current->flags & EXEC_CKD)) && (current->flags & WRAP_FLAG) ) {

< current->flags |= EXEC_CKD;

< if (file) {

< allow_write_access(file);

< fput(file);

< }

< for (i = 0 ; i < MAX_ARG_PAGES ; i++) {

< struct page * page = bprm.page[i];

< if (page)

< __free_page(page);

< }

< return do_execve(filename, argv, envp, regs);

< }

< else {

< current->flags &= ~EXEC_CKD;

< }

---

> retval = copy_strings(bprm.argc, argv, &bprm);

> if (retval < 0)

> goto out;

1274,1275c907

< if (retval >= 0) {

---

> if (retval >= 0)

1277,1278c909

< return retval;

< }

---

> return retval;

1282,1288c913,915

< if (file) {

< allow_write_access(file);

< fput(file);

< }

---

> allow_write_access(bprm.file);

> if (bprm.file)

> fput(bprm.file);

1295,1297d921

< current->flags &= ~EXEC_CKD;

# diff sched.h /u/usr/src/linux-2.4.18/include/linux/sched.h

32,37d31

< #define WRAP_PATH "/root/wrap" /* location of the execve wrapper executable */

< #define WRAP_THRESH 20 /* don't run wrapper on PIDs less than this threshold */

<

439,443d432

< #define WRAP_FLAG 0x08000000 /* Process has been wrapped */

< #define EXEC_CKD 0x04000000 /* Process has been checked for exec errors */

453,456d441

< #define PT_HIDETRACE 0x0000020 /* conceal wrapper from execution trace */

# diff process.c /u/usr/src/linux-2.4.18/arch/i386/kernel/process.c

774d773

777,784d775

< * DTK:

< * If the WRAP_FLAG is on, this is the wrapper's execve call.

< * - Turn off the wrap flag

< * - Turn execution tracing back on

< * If the WRAP_FLAG is off, this is the user's execve call.

< * - Turn on the wrap flag

< * - Turn off the execution trace for this call

795,815d785

< /*** DTK-- ***/

< if (current->pid < WRAP_THRESH) {

< /* Do nothing-- don't run wrapper on boot-up */

< }

< else if ((current->flags) & WRAP_FLAG) {

< current->flags &= ~WRAP_FLAG;

< if (current->ptrace & PT_HIDETRACE) {

< current->ptrace |= PT_PTRACED;

< current->ptrace &= ~PT_HIDETRACE;

< }

< }

< else {

< current->flags |= WRAP_FLAG;

< if (current->ptrace & PT_PTRACED) {

< current->ptrace |= PT_HIDETRACE;

< current->ptrace &= ~PT_PTRACED;

< }

< }

817,821c787,788

< if (error == 0) {

< current->ptrace &= ~PT_DTRACE;

< }

---

> if (error == 0)

> current->ptrace &= ~PT_DTRACE;

824,833d790

< if (error != 0) {

< //printk(KERN_CRIT "ERROR:%d (%s)\n", error, filename);

< current->flags &= ~WRAP_FLAG;

< if (current->ptrace & PT_HIDETRACE) {

< current->ptrace |= PT_PTRACED;

< current->ptrace &= ~PT_HIDETRACE;

< }

< }

< /*** --DTK ***/

836d792

# diff entry.S /u/usr/src/linux-2.4.18/arch/i386/kernel/entry.S

399c399

< .long SYMBOL_NAME(sys_ad) /* 0 - old "setup()" system call*/

---

> .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/

# diff ksyms.c /u/usr/src/linux-2.4.18/kernel/ksyms.c

75,103d74

< //------------dcvn------------------------------

< //needed for the EXPORT_SYMBOL declarations

< #define UIDHASH_BITS 8

< #define UIDHASH_SZ (1 << UIDHASH_BITS)

< extern kmem_cache_t *uid_cachep;

< extern struct user_struct *uidhash_table[UIDHASH_SZ];

< extern spinlock_t uidhash_lock;

< extern kmem_cache_t *dn_cache;

< extern rwlock_t dn_lock;

< extern int sock_map_fd(struct socket *sock);

< extern struct module * module_list;

< //------------------dcvn-------------------

< /* extra symbols needed for kernel module */

< //dcvn

< EXPORT_SYMBOL(uid_cachep); //for setuid sys_calls

< EXPORT_SYMBOL(uidhash_lock);

< EXPORT_SYMBOL(uidhash_table);

< EXPORT_SYMBOL(dn_lock); //for write() sys_call

< EXPORT_SYMBOL(dn_cache);

< EXPORT_SYMBOL(do_truncate);

< EXPORT_SYMBOL(sock_map_fd);

< EXPORT_SYMBOL(module_list);

< /* original code from here on */

# diff user.c /u/usr/src/linux-2.4.18/kernel/user.c

25,27c25,27

< kmem_cache_t *uid_cachep;

< struct user_struct *uidhash_table[UIDHASH_SZ];

< spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;

---

> static kmem_cache_t *uid_cachep;

> static struct user_struct *uidhash_table[UIDHASH_SZ];

> static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;

# diff dnotify.c /u/usr/src/linux-2.4.18/fs/dnotify.c

27,28c27,28

< rwlock_t dn_lock = RW_LOCK_UNLOCKED;

< kmem_cache_t *dn_cache;

---

> static rwlock_t dn_lock = RW_LOCK_UNLOCKED;

> static kmem_cache_t *dn_cache;

# module.c

This is the module.c code. I believe the 'diff' file includes

modifications to this, however, this is the current version. This code

is a modified version of a free module that intercepts system calls.

It has been modified to provide the deception and control capabilities.

#include <linux/config.h>

#include <linux/mm.h>

#include <linux/module.h>

#include <asm/module.h>

#include <asm/uaccess.h>

#include <linux/vmalloc.h>

#include <linux/smp_lock.h>

#include <asm/pgalloc.h>

#include <linux/init.h>

#include <linux/slab.h>

#include <linux/kmod.h>

#include <linux/seq_file.h>

#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)

extern struct module_symbol __start___ksymtab[];

extern struct module_symbol __stop___ksymtab[];

extern const struct exception_table_entry __start___ex_table[];

extern const struct exception_table_entry __stop___ex_table[];

extern const char __start___kallsyms[] __attribute__ ((weak));

extern const char __stop___kallsyms[] __attribute__ ((weak));

struct module kernel_module =

{

size_of_struct: sizeof(struct module),

name: "",

uc: {ATOMIC_INIT(1)},

flags: MOD_RUNNING,

syms: __start___ksymtab,

ex_table_start: __start___ex_table,

ex_table_end: __stop___ex_table,

kallsyms_start: __start___kallsyms,

kallsyms_end: __stop___kallsyms,

};

struct module *module_list = &kernel_module;

#endif /* defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS) */

/* inter_module functions are always available, even when the kernel is

* compiled without modules. Consumers of inter_module_xxx routines

* will always work, even when both are built into the kernel, this

* approach removes lots of #ifdefs in mainline code. */

static struct list_head ime_list = LIST_HEAD_INIT(ime_list);

static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;

static int kmalloc_failed;

/* This lock prevents modifications that might race the kernel fault

* fixups. It does not prevent reader walks that the modules code

* does. The kernel lock does that.

* Since vmalloc fault fixups occur in any context this lock is taken

* irqsave at all times. */

spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;

/* inter_module_register - register a new set of inter module data.

* @im_name: an arbitrary string to identify the data, must be unique

* @owner: module that is registering the data, always use THIS_MODULE

* @userdata: pointer to arbitrary userdata to be registered

* Description: Check that the im_name has not already been registered,

* complain if it has. For new data, add it to the inter_module_entry

* list.*/

void inter_module_register(const char *im_name, struct module *owner, const void *userdata)

{

struct list_head *tmp;

struct inter_module_entry *ime, *ime_new;

if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {

/* Overloaded kernel, not fatal */

printk(KERN_ERR

"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",

im_name);

kmalloc_failed = 1;

return;

}

memset(ime_new, 0, sizeof(*ime_new));

ime_new->im_name = im_name;

ime_new->owner = owner;

ime_new->userdata = userdata;

spin_lock(&ime_lock);

list_for_each(tmp, &ime_list) {

ime = list_entry(tmp, struct inter_module_entry, list);

if (strcmp(ime->im_name, im_name) == 0) {

spin_unlock(&ime_lock);

kfree(ime_new);

/* Program logic error, fatal */

printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);

BUG();

} }

list_add(&(ime_new->list), &ime_list);

spin_unlock(&ime_lock);

}

/* inter_module_unregister - unregister a set of inter module data.

* @im_name: an arbitrary string to identify the data, must be unique

* Description: Check that the im_name has been registered, complain if

* it has not. For existing data, remove it from the

* inter_module_entry list. */

void inter_module_unregister(const char *im_name)

{

struct list_head *tmp;

struct inter_module_entry *ime;

spin_lock(&ime_lock);

list_for_each(tmp, &ime_list) {

ime = list_entry(tmp, struct inter_module_entry, list);

if (strcmp(ime->im_name, im_name) == 0) {

list_del(&(ime->list));

spin_unlock(&ime_lock);

kfree(ime);

return;

}

}

spin_unlock(&ime_lock);

if (kmalloc_failed) {

printk(KERN_ERR

"inter_module_unregister: no entry for '%s', "

"probably caused by previous kmalloc failure\n",

im_name);

return;

}

else {

/* Program logic error, fatal */

printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);

BUG();

}

}

/**

* inter_module_get - return arbitrary userdata from another module.

* @im_name: an arbitrary string to identify the data, must be unique

* Description: If the im_name has not been registered, return NULL.

* Try to increment the use count on the owning module, if that fails

* then return NULL. Otherwise return the userdata.*/

const void *inter_module_get(const char *im_name)

{

struct list_head *tmp;

struct inter_module_entry *ime;

const void *result = NULL;

spin_lock(&ime_lock);

list_for_each(tmp, &ime_list) {

ime = list_entry(tmp, struct inter_module_entry, list);

if (strcmp(ime->im_name, im_name) == 0) {

if (try_inc_mod_count(ime->owner))

result = ime->userdata;

break;

}

}

spin_unlock(&ime_lock);

return(result);

}

/**

* inter_module_get_request - im get with automatic request_module.

* @im_name: an arbitrary string to identify the data, must be unique

* @modname: module that is expected to register im_name

*

* Description: If inter_module_get fails, do request_module then retry.*/

const void *inter_module_get_request(const char *im_name, const char *modname)

{

const void *result = inter_module_get(im_name);

if (!result) {

request_module(modname);

result = inter_module_get(im_name);

}

return(result);

}

/* * inter_module_put - release use of data from another module.

* @im_name: an arbitrary string to identify the data, must be unique

* Description: If the im_name has not been registered, complain,

* otherwise decrement the use count on the owning module.*/

void inter_module_put(const char *im_name)

{

struct list_head *tmp;

struct inter_module_entry *ime;

spin_lock(&ime_lock);

list_for_each(tmp, &ime_list) {

ime = list_entry(tmp, struct inter_module_entry, list);

if (strcmp(ime->im_name, im_name) == 0) {

if (ime->owner)

__MOD_DEC_USE_COUNT(ime->owner);

spin_unlock(&ime_lock);

return;

}

}

spin_unlock(&ime_lock);

printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);

BUG();

}

#if defined(CONFIG_MODULES) /* The rest of the source */

static long get_mod_name(const char *user_name, char **buf);

static void put_mod_name(char *buf);

struct module *find_module(const char *name);

void free_module(struct module *, int tag_freed);

/*Called at boot time*/

void __init init_modules(void)

{

kernel_module.nsyms = __stop___ksymtab - __start___ksymtab;

arch_init_modules(&kernel_module);

}

/*Copy the name of a module from user space.*/

static inline long

get_mod_name(const char *user_name, char **buf)

{

unsigned long page;

long retval;

page = __get_free_page(GFP_KERNEL);

if (!page)

return -ENOMEM;

retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);

if (retval > 0) {

if (retval < PAGE_SIZE) {

*buf = (char *)page;

return retval;

}

retval = -ENAMETOOLONG;

} else if (!retval)

retval = -EINVAL;

free_page(page);

return retval;

}

static inline void

put_mod_name(char *buf)

{

free_page((unsigned long)buf);

}

/*Allocate space for a module.*/

asmlinkage unsigned long

sys_create_module(const char *name_user, size_t size)

{

char *name;

long namelen, error;

struct module *mod;

unsigned long flags;

if (!capable(CAP_SYS_MODULE))

return -EPERM;

lock_kernel();

if ((namelen = get_mod_name(name_user, &name)) < 0) {

error = namelen;

goto err0;

}

if (size < sizeof(struct module)+namelen) {

error = -EINVAL;

goto err1;

}

if (find_module(name) != NULL) {

error = -EEXIST;

goto err1;

}

if ((mod = (struct module *)module_map(size)) == NULL) {

error = -ENOMEM;

goto err1;

}

memset(mod, 0, sizeof(*mod));

mod->size_of_struct = sizeof(*mod);

mod->name = (char *)(mod + 1);

mod->size = size;

memcpy((char*)(mod+1), name, namelen+1);

put_mod_name(name);

spin_lock_irqsave(&modlist_lock, flags);

mod->next = module_list;

module_list = mod; /* link it in */

spin_unlock_irqrestore(&modlist_lock, flags);

error = (long) mod;

goto err0;

err1:

put_mod_name(name);

err0:

unlock_kernel();

return error;

}

/*Initialize a module.*/

asmlinkage long

sys_init_module(const char *name_user, struct module *mod_user)

{

struct module mod_tmp, *mod;

char *name, *n_name, *name_tmp = NULL;

long namelen, n_namelen, i, error;

unsigned long mod_user_size;

struct module_ref *dep;

if (!capable(CAP_SYS_MODULE))

return -EPERM;

lock_kernel();

if ((namelen = get_mod_name(name_user, &name)) < 0) {

error = namelen;

goto err0;

}

if ((mod = find_module(name)) == NULL) {

error = -ENOENT;

goto err1;

}

/* Check module header size. We allow a bit of slop over the

size we are familiar with to cope with a version of insmod

for a newer kernel. But don't over do it. */

if ((error = get_user(mod_user_size, &mod_user->size_of_struct)) != 0)

goto err1;

if (mod_user_size < (unsigned long)&((struct module *)0L)->persist_start

|| mod_user_size > sizeof(struct module) + 16*sizeof(void*)) {

printk(KERN_ERR "init_module: Invalid module header size.\n"

KERN_ERR "A new version of the modutils is likely "

"needed.\n");

error = -EINVAL;

goto err1;

}

/* Hold the current contents while we play with the user's idea

of righteousness. */

mod_tmp = *mod;

name_tmp = kmalloc(strlen(mod->name) + 1, GFP_KERNEL); /* Where's kstrdup()? */

if (name_tmp == NULL) {

error = -ENOMEM;

goto err1;

}

strcpy(name_tmp, mod->name);

error = copy_from_user(mod, mod_user, mod_user_size);

if (error) {

error = -EFAULT;

goto err2;

}

/* Sanity check the size of the module. */

error = -EINVAL;

if (mod->size > mod_tmp.size) {

printk(KERN_ERR "init_module: Size of initialized module "

"exceeds size of created module.\n");

goto err2;

}

/* Make sure all interesting pointers are sane. */

if (!mod_bound(mod->name, namelen, mod)) {

printk(KERN_ERR "init_module: mod->name out of bounds.\n");

goto err2;

}

if (mod->nsyms && !mod_bound(mod->syms, mod->nsyms, mod)) {

printk(KERN_ERR "init_module: mod->syms out of bounds.\n");

goto err2;

}

if (mod->ndeps && !mod_bound(mod->deps, mod->ndeps, mod)) {

printk(KERN_ERR "init_module: mod->deps out of bounds.\n");

goto err2;

}

if (mod->init && !mod_bound(mod->init, 0, mod)) {

printk(KERN_ERR "init_module: mod->init out of bounds.\n");

goto err2;

}

if (mod->cleanup && !mod_bound(mod->cleanup, 0, mod)) {

printk(KERN_ERR "init_module: mod->cleanup out of bounds.\n");

goto err2;

}

if (mod->ex_table_start > mod->ex_table_end

|| (mod->ex_table_start &&

!((unsigned long)mod->ex_table_start >= ((unsigned long)mod + mod->size_of_struct)

&& ((unsigned long)mod->ex_table_end

< (unsigned long)mod + mod->size)))

|| (((unsigned long)mod->ex_table_start

- (unsigned long)mod->ex_table_end)

% sizeof(struct exception_table_entry))) {

printk(KERN_ERR "init_module: mod->ex_table_* invalid.\n");

goto err2;

}

if (mod->flags & ~MOD_AUTOCLEAN) {

printk(KERN_ERR "init_module: mod->flags invalid.\n");

goto err2;

}

if (mod_member_present(mod, can_unload)

&& mod->can_unload && !mod_bound(mod->can_unload, 0, mod)) {

printk(KERN_ERR "init_module: mod->can_unload out of bounds.\n");

goto err2;

}

if (mod_member_present(mod, kallsyms_end)) {

if (mod->kallsyms_end &&

(!mod_bound(mod->kallsyms_start, 0, mod) ||

!mod_bound(mod->kallsyms_end, 0, mod))) {

printk(KERN_ERR "init_module: mod->kallsyms out of bounds.\n");

goto err2;

}

if (mod->kallsyms_start > mod->kallsyms_end) {

printk(KERN_ERR "init_module: mod->kallsyms invalid.\n");

goto err2;

}

}

if (mod_member_present(mod, archdata_end)) {

if (mod->archdata_end &&

(!mod_bound(mod->archdata_start, 0, mod) ||

!mod_bound(mod->archdata_end, 0, mod))) {

printk(KERN_ERR "init_module: mod->archdata out of bounds.\n");

goto err2;

}

if (mod->archdata_start > mod->archdata_end) {

printk(KERN_ERR "init_module: mod->archdata invalid.\n");

goto err2;

}

}

if (mod_member_present(mod, kernel_data) && mod->kernel_data) {

printk(KERN_ERR "init_module: mod->kernel_data must be zero.\n");

goto err2;

}

/* Check that the user isn't doing something silly with the name. */

if ((n_namelen = get_mod_name(mod->name - (unsigned long)mod

+ (unsigned long)mod_user,

&n_name)) < 0) {

printk(KERN_ERR "init_module: get_mod_name failure.\n");

error = n_namelen;

goto err2;

}

if (namelen != n_namelen || strcmp(n_name, mod_tmp.name) != 0) {

printk(KERN_ERR "init_module: changed module name to "

"`%s' from `%s'\n",

n_name, mod_tmp.name);

goto err3;

}

/* Ok, that's about all the sanity we can stomach; copy the rest. */

if (copy_from_user((char *)mod+mod_user_size,

(char *)mod_user+mod_user_size,

mod->size-mod_user_size)) {

error = -EFAULT;

goto err3;

}

if (module_arch_init(mod))

goto err3;

/* On some machines it is necessary to do something here

to make the I and D caches consistent. */

flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);

mod->next = mod_tmp.next;

mod->refs = NULL;

/* Sanity check the module's dependents */

for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {

struct module *o, *d = dep->dep;

/* Make sure the indicated dependencies are really modules. */

if (d == mod) {

printk(KERN_ERR "init_module: self-referential "

"dependency in mod->deps.\n");

goto err3;

}

/* Scan the current modules for this dependency */

for (o = module_list; o != &kernel_module && o != d; o = o->next)

;

if (o != d) {

printk(KERN_ERR "init_module: found dependency that is "

"(no longer?) a module.\n");

goto err3;

}

}

/* Update module references. */

for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {

struct module *d = dep->dep;

dep->ref = mod;

dep->next_ref = d->refs;

d->refs = dep;

/* Being referenced by a dependent module counts as a

use as far as kmod is concerned. */

d->flags |= MOD_USED_ONCE;

}

/* Free our temporary memory. */

put_mod_name(n_name);

put_mod_name(name);

/* Initialize the module. */

atomic_set(&mod->uc.usecount,1);

mod->flags |= MOD_INITIALIZING;

if (mod->init && (error = mod->init()) != 0) {

atomic_set(&mod->uc.usecount,0);

mod->flags &= ~MOD_INITIALIZING;

if (error > 0) /* Buggy module */

error = -EBUSY;

goto err0;

}

atomic_dec(&mod->uc.usecount);

/* And set it running. */

mod->flags = (mod->flags | MOD_RUNNING) & ~MOD_INITIALIZING;

error = 0;

goto err0;

err3:

put_mod_name(n_name);

err2:

*mod = mod_tmp;

strcpy((char *)mod->name, name_tmp); /* We know there is room for this */

err1:

put_mod_name(name);

err0:

unlock_kernel();

kfree(name_tmp);

return error;

}

spinlock_t unload_lock = SPIN_LOCK_UNLOCKED;

int try_inc_mod_count(struct module *mod)

{

int res = 1;

if (mod) {

spin_lock(&unload_lock);

if (mod->flags & MOD_DELETED)

res = 0;

else

__MOD_INC_USE_COUNT(mod);

spin_unlock(&unload_lock);

}

return res;

}

asmlinkage long

sys_delete_module(const char *name_user)

{

struct module *mod, *next;

char *name;

long error;

int something_changed;

if (!capable(CAP_SYS_MODULE))

return -EPERM;

lock_kernel();

if (name_user) {

if ((error = get_mod_name(name_user, &name)) < 0)

goto out;

error = -ENOENT;

if ((mod = find_module(name)) == NULL) {

put_mod_name(name);

goto out;

}

put_mod_name(name);

error = -EBUSY;

if (mod->refs != NULL)

goto out;

spin_lock(&unload_lock);

if (!__MOD_IN_USE(mod)) {

mod->flags |= MOD_DELETED;

spin_unlock(&unload_lock);

free_module(mod, 0);

error = 0;

} else {

spin_unlock(&unload_lock);

}

goto out;

}

/* Do automatic reaping */

restart:

something_changed = 0;

for (mod = module_list; mod != &kernel_module; mod = next) {

next = mod->next;

spin_lock(&unload_lock);

if (mod->refs == NULL

&& (mod->flags & MOD_AUTOCLEAN)

&& (mod->flags & MOD_RUNNING)

&& !(mod->flags & MOD_DELETED)

&& (mod->flags & MOD_USED_ONCE)

&& !__MOD_IN_USE(mod)) {

if ((mod->flags & MOD_VISITED)

&& !(mod->flags & MOD_JUST_FREED)) {

spin_unlock(&unload_lock);

mod->flags &= ~MOD_VISITED;

} else {

mod->flags |= MOD_DELETED;

spin_unlock(&unload_lock);

free_module(mod, 1);

something_changed = 1;

}

} else {

spin_unlock(&unload_lock);

}

}

if (something_changed)

goto restart;

for (mod = module_list; mod != &kernel_module; mod = mod->next)

mod->flags &= ~MOD_JUST_FREED;

error = 0;

out:

unlock_kernel();

return error;

}

/* Query various bits about modules. */

static int

qm_modules(char *buf, size_t bufsize, size_t *ret)

{

struct module *mod;

size_t nmod, space, len;

nmod = space = 0;

for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {

len = strlen(mod->name)+1;

if (len > bufsize)

goto calc_space_needed;

if (copy_to_user(buf, mod->name, len))

return -EFAULT;

buf += len;

bufsize -= len;

space += len;

}

if (put_user(nmod, ret))

return -EFAULT;

else

return 0;

calc_space_needed:

space += len;

while ((mod = mod->next) != &kernel_module)

space += strlen(mod->name)+1;

if (put_user(space, ret))

return -EFAULT;

else

return -ENOSPC;

}

static int

qm_deps(struct module *mod, char *buf, size_t bufsize, size_t *ret)

{

size_t i, space, len;

if (mod == &kernel_module)

return -EINVAL;

if (!MOD_CAN_QUERY(mod))

if (put_user(0, ret))

return -EFAULT;

else

return 0;

space = 0;

for (i = 0; i < mod->ndeps; ++i) {

const char *dep_name = mod->deps[i].dep->name;

len = strlen(dep_name)+1;

if (len > bufsize)

goto calc_space_needed;

if (copy_to_user(buf, dep_name, len))

return -EFAULT;

buf += len;

bufsize -= len;

space += len;

}

if (put_user(i, ret))

return -EFAULT;

else

return 0;

calc_space_needed:

space += len;

while (++i < mod->ndeps)

space += strlen(mod->deps[i].dep->name)+1;

if (put_user(space, ret))

return -EFAULT;

else

return -ENOSPC;

}

static int

qm_refs(struct module *mod, char *buf, size_t bufsize, size_t *ret)

{

size_t nrefs, space, len;

struct module_ref *ref;

if (mod == &kernel_module)

return -EINVAL;

if (!MOD_CAN_QUERY(mod))

if (put_user(0, ret))

return -EFAULT;

else

return 0;

space = 0;

for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {

const char *ref_name = ref->ref->name;

len = strlen(ref_name)+1;

if (len > bufsize)

goto calc_space_needed;

if (copy_to_user(buf, ref_name, len))

return -EFAULT;

buf += len;

bufsize -= len;

space += len;

}

if (put_user(nrefs, ret))

return -EFAULT;

else

return 0;

calc_space_needed:

space += len;

while ((ref = ref->next_ref) != NULL)

space += strlen(ref->ref->name)+1;

if (put_user(space, ret))

return -EFAULT;

else

return -ENOSPC;

}

static int

qm_symbols(struct module *mod, char *buf, size_t bufsize, size_t *ret)

{

size_t i, space, len;

struct module_symbol *s;

char *strings;

unsigned long *vals;

if (!MOD_CAN_QUERY(mod))

if (put_user(0, ret))

return -EFAULT;

else

return 0;

space = mod->nsyms * 2*sizeof(void *);

i = len = 0;

s = mod->syms;

if (space > bufsize)

goto calc_space_needed;

if (!access_ok(VERIFY_WRITE, buf, space))

return -EFAULT;



bufsize -= space;

vals = (unsigned long *)buf;

strings = buf+space;

for (; i < mod->nsyms ; ++i, ++s, vals += 2) {

len = strlen(s->name)+1;

if (len > bufsize)

goto calc_space_needed;

if (copy_to_user(strings, s->name, len)

|| __put_user(s->value, vals+0)

|| __put_user(space, vals+1))

return -EFAULT;

strings += len;

bufsize -= len;

space += len;

}

if (put_user(i, ret))

return -EFAULT;

else

return 0;

calc_space_needed:

for (; i < mod->nsyms; ++i, ++s)

space += strlen(s->name)+1;

if (put_user(space, ret))

return -EFAULT;

else

return -ENOSPC;

}

static int

qm_info(struct module *mod, char *buf, size_t bufsize, size_t *ret)

{

int error = 0;

if (mod == &kernel_module)


return -EINVAL;

if (sizeof(struct module_info) <= bufsize) {

struct module_info info;

info.addr = (unsigned long)mod;

info.size = mod->size;

info.flags = mod->flags;

/* usecount is one too high here - report appropriately to

compensate for locking */

info.usecount = (mod_member_present(mod, can_unload)

&& mod->can_unload ? -1 : atomic_read(&mod->uc.usecount)-1);

if (copy_to_user(buf, &info, sizeof(struct module_info)))

return -EFAULT;

} else

error = -ENOSPC;

if (put_user(sizeof(struct module_info), ret))

return -EFAULT;

return error;

}

asmlinkage long

sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,

size_t *ret)

{

struct module *mod;

int err;

lock_kernel();

if (name_user == NULL)

mod = &kernel_module;

else {

long namelen;

char *name;

if ((namelen = get_mod_name(name_user, &name)) < 0) {

err = namelen;

goto out;

}

err = -ENOENT;

if ((mod = find_module(name)) == NULL) {

put_mod_name(name);

goto out;

}

put_mod_name(name);

}

/* __MOD_ touches the flags. We must avoid that */

atomic_inc(&mod->uc.usecount);

switch (which)

{

case 0:

err = 0;

break;

case QM_MODULES:

err = qm_modules(buf, bufsize, ret);

break;

case QM_DEPS:

err = qm_deps(mod, buf, bufsize, ret);

break;

case QM_REFS:

err = qm_refs(mod, buf, bufsize, ret);

break;

case QM_SYMBOLS:

err = qm_symbols(mod, buf, bufsize, ret);

break;

case QM_INFO:

err = qm_info(mod, buf, bufsize, ret);

break;

default:

err = -EINVAL;

break;

}

atomic_dec(&mod->uc.usecount);

out:

unlock_kernel();

return err;

}

/*Copy the kernel symbol table to user space. If the argument is

* NULL, just return the size of the table.

*

* This call is obsolete. New programs should use query_module+QM_SYMBOLS

* which does not arbitrarily limit the length of symbols.*/

asmlinkage long

sys_get_kernel_syms(struct kernel_sym *table)

{


struct module *mod;

int i;

struct kernel_sym ksym;

lock_kernel();

for (mod = module_list, i = 0; mod; mod = mod->next) {

/* include the count for the module name! */

i += mod->nsyms + 1;

}

if (table == NULL)

goto out;

/* So that we don't give the user our stack content */

memset (&ksym, 0, sizeof (ksym));

for (mod = module_list, i = 0; mod; mod = mod->next) {

struct module_symbol *msym;

unsigned int j;

if (!MOD_CAN_QUERY(mod))

continue;

/* magic: write module info as a pseudo symbol */

ksym.value = (unsigned long)mod;

ksym.name[0] = '#';

strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);

ksym.name[sizeof(ksym.name)-1] = '\0';

if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)

goto out;

++i, ++table;

if (mod->nsyms == 0)

continue;

for (j = 0, msym = mod->syms; j < mod->nsyms; ++j, ++msym) {

ksym.value = msym->value;

strncpy(ksym.name, msym->name, sizeof(ksym.name));

ksym.name[sizeof(ksym.name)-1] = '\0';

if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)

goto out;

++i, ++table;

}

}

out:

unlock_kernel();

return i;

}

/*Look for a module by name, ignoring modules marked for deletion.*/

struct module *

find_module(const char *name)

{

struct module *mod;

for (mod = module_list; mod ; mod = mod->next) {

if (mod->flags & MOD_DELETED)

continue;

if (!strcmp(mod->name, name))

break;

}

return mod;

}

/*Free the given module.*/

void

free_module(struct module *mod, int tag_freed)

{

struct module_ref *dep;

unsigned i;

unsigned long flags;

/* Let the module clean up. */

if (mod->flags & MOD_RUNNING)

{

if(mod->cleanup)

mod->cleanup();

mod->flags &= ~MOD_RUNNING;

}

/* Remove the module from the dependency lists. */

for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {

struct module_ref **pp;

for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)

continue;

*pp = dep->next_ref;

if (tag_freed && dep->dep->refs == NULL)

dep->dep->flags |= MOD_JUST_FREED;

}

/* And from the main module list. */

spin_lock_irqsave(&modlist_lock, flags);

if (mod == module_list) {

module_list = mod->next;

} else {

struct module *p;

for (p = module_list; p->next != mod; p = p->next)

continue;

p->next = mod->next;

}

spin_unlock_irqrestore(&modlist_lock, flags);

/* And free the memory. */

module_unmap(mod);

}

/*Called by the /proc file system to return a current list of modules.*/

int get_module_list(char *p)

{

size_t left = PAGE_SIZE;

struct module *mod;

char tmpstr[64];

struct module_ref *ref;

for (mod = module_list; mod != &kernel_module; mod = mod->next) {

long len;

const char *q;

#define safe_copy_str(str, len) \

do { \

if (left < len) \

goto fini; \

memcpy(p, str, len); p += len, left -= len; \

} while (0)

#define safe_copy_cstr(str) safe_copy_str(str, sizeof(str)-1)

len = strlen(mod->name);

safe_copy_str(mod->name, len);

if ((len = 20 - len) > 0) {

if (left < len)

goto fini;

memset(p, ' ', len);

p += len;

left -= len;

}

len = sprintf(tmpstr, "%8lu", mod->size);

safe_copy_str(tmpstr, len);

if (mod->flags & MOD_RUNNING) {

len = sprintf(tmpstr, "%4ld",

(mod_member_present(mod, can_unload)

&& mod->can_unload

? -1L : (long)atomic_read(&mod->uc.usecount)));

safe_copy_str(tmpstr, len);

}

if (mod->flags & MOD_DELETED)

safe_copy_cstr(" (deleted)");

else if (mod->flags & MOD_RUNNING) {

if (mod->flags & MOD_AUTOCLEAN)

safe_copy_cstr(" (autoclean)");

if (!(mod->flags & MOD_USED_ONCE))

safe_copy_cstr(" (unused)");

}

else if (mod->flags & MOD_INITIALIZING)

safe_copy_cstr(" (initializing)");

else

safe_copy_cstr(" (uninitialized)");

if ((ref = mod->refs) != NULL) {

safe_copy_cstr(" [");

while (1) {

q = ref->ref->name;

len = strlen(q);

safe_copy_str(q, len);

if ((ref = ref->next_ref) != NULL)

safe_copy_cstr(" ");

else

break;

}

safe_copy_cstr("]");

}

safe_copy_cstr("\n");

#undef safe_copy_str

#undef safe_copy_cstr

}

fini:

return PAGE_SIZE - left;

}

/*Called by the /proc file system to return a current list of ksyms.*/

struct mod_sym {

struct module *mod;

int index;

};

/* iterator */

static void *s_start(struct seq_file *m, loff_t *pos)

{

struct mod_sym *p = kmalloc(sizeof(*p), GFP_KERNEL);

struct module *v;

loff_t n = *pos;

if (!p)

return ERR_PTR(-ENOMEM);

lock_kernel();

for (v = module_list, n = *pos; v; n -= v->nsyms, v = v->next) {

if (n < v->nsyms) {

p->mod = v;

p->index = n;

return p;

}

}

unlock_kernel();

kfree(p);

return NULL;

}

static void *s_next(struct seq_file *m, void *p, loff_t *pos)

{

struct mod_sym *v = p;

(*pos)++;

if (++v->index >= v->mod->nsyms) {

do {

v->mod = v->mod->next;

if (!v->mod) {

unlock_kernel();

kfree(p);

return NULL;

}

} while (!v->mod->nsyms);

v->index = 0;

}

return p;

}

static void s_stop(struct seq_file *m, void *p)

{

if (p && !IS_ERR(p)) {

unlock_kernel();

kfree(p);

}

}

static int s_show(struct seq_file *m, void *p)

{

struct mod_sym *v = p;

struct module_symbol *sym;

if (!MOD_CAN_QUERY(v->mod))

return 0;

sym = &v->mod->syms[v->index];

if (*v->mod->name)

seq_printf(m, "%0*lx %s\t[%s]\n", (int)(2*sizeof(void*)),

sym->value, sym->name, v->mod->name);

else

seq_printf(m, "%0*lx %s\n", (int)(2*sizeof(void*)),

sym->value, sym->name);

return 0;

}

struct seq_operations ksyms_op = {

start: s_start,

next: s_next,

stop: s_stop,

show: s_show

};

#else /* CONFIG_MODULES */

/* Dummy syscalls for people who don't want modules */

asmlinkage unsigned long

sys_create_module(const char *name_user, size_t size)

{

return -ENOSYS;

}

asmlinkage long

sys_init_module(const char *name_user, struct module *mod_user)

{

return -ENOSYS;

}

asmlinkage long

sys_delete_module(const char *name_user)

{

return -ENOSYS;

}

asmlinkage long

sys_query_module(const char *name_user, int which, char *buf, size_t bufsize,

size_t *ret)

{

/* Let the program know about the new interface. Not that

it'll do them much good. */

if (which == 0)

return 0;

return -ENOSYS;

}

asmlinkage long

sys_get_kernel_syms(struct kernel_sym *table)

{

return -ENOSYS;

}

int try_inc_mod_count(struct module *mod)

{

return 1;

}

#endif /* CONFIG_MODULES */


Cohen et al. Example Source Code Appendix Page 54 of 54 QILPG 529-000200US