[Small-cl-src] root.lisp

Luke Gorrie luke at bluetail.com
Fri May 14 11:24:32 UTC 2004


;;; root.lisp -- superuser-when-it-suits-me privilege managemenet (for CMUCL)
;;; Written by Luke Gorrie <luke at bluetail.com>, July 2003.
;;
;; This package implements a convenient security loophole: it allows
;; you to become root temporarily, whenever you please. This is useful
;; if you sometimes need to do privileged operations but don't want
;; Lisp to always run as root (mucking up your file permissions, etc).
;;
;; WARNING: Only use this package if you understand how it works,
;; and/or don't mind users of your machine becoming root at will! To
;; understand how it works, refer to Stevens' _Advanced Programming in
;; the Unix Environment_, or ask your local Unix guru.
;;
;; To setup:
;;
;;   Compile this package, and either add it to your image or load it
;;   in your init file.
;;
;;   Add the following line to your init file:
;;     #+root (root:condescend)
;;
;;   Make your 'lisp' process setuid-root:
;;     chown root `which lisp`
;;     chmod u+s `which lisp`
;;
;; Now your Lisp system will start as root, but quickly switch to your
;; real user. Whenever you want to run some code as root, you need
;; only write:
;;
;;   (root:as-superuser ...naughty code...)
;;
;; You can test by writing (list (root::geteuid)
;;                               (root:as-superuser (root::geteuid)))
;;
;; which should return (<your-real-uid> 0).

(defpackage :root
  (:use :common-lisp :unix :alien :c-call)
  (:export :condescend :as-superuser))

(in-package :root)

(defun condescend ()
  "Switch down from the superuser, with the option to switch back.
\(Sets the effective user to the real user, and the real user to root.)
Returns T on success, or NIL if we weren't the superuser."
  (values (unix-setreuid 0 (unix-getuid))))

(defmacro as-superuser (&body forms)
  "Execute FORMS as the superuser."
  `(let ((old-euid (geteuid)))
    (unwind-protect
         (if (unix-setreuid 0 0)
             (progn , at forms)
             (error "Failed to become superuser"))
      (unix-setreuid 0 old-euid))))

;; CMUCL 18e's unix-glibc2.lisp has this #+NIL'd out, so here it is.
(def-alien-routine ("geteuid" geteuid) int
  "Get the effective user ID of the calling process.")

(pushnew :root *features*)




More information about the Small-cl-src mailing list