~ruther/guix-local

909147e43f8c9f8c9b9d33597d5dd83facca699c — Ricardo Wurmus 10 years ago 8e9ba61
services: Add pam-limits-service.

* gnu/system/pam.scm (<pam-limits-entry>): New record type.
(pam-limits-entry, pam-limits-entry->string): New procedures.
* gnu/services/base.scm (pam-limits-service-type): New variable.
(pam-limits-service): New procedure.
* doc/guix.texi (Base Services): Document it.
3 files changed, 134 insertions(+), 0 deletions(-)

M doc/guix.texi
M gnu/services/base.scm
M gnu/system/pam.scm
M doc/guix.texi => doc/guix.texi +30 -0
@@ 17,6 17,7 @@ Copyright @copyright{} 2015, 2016 Mathieu Lirzin@*
Copyright @copyright{} 2014 Pierre-Antoine Rault@*
Copyright @copyright{} 2015 Taylan Ulrich Bayırlı/Kammer@*
Copyright @copyright{} 2015, 2016 Leo Famulari@*
Copyright @copyright{} 2015, 2016 Ricardo Wurmus@*
Copyright @copyright{} 2016 Ben Woodcroft@*
Copyright @copyright{} 2016 Chris Marusich@*
Copyright @copyright{} 2016 Efraim Flashner


@@ 7570,6 7571,35 @@ to add @var{device} to the kernel's entropy pool.  The service will fail if
@var{device} does not exist.
@end deffn

@anchor{pam-limits-service}
@cindex session limits
@cindex ulimit
@cindex priority
@deffn {Scheme Procedure} pam-limits-service [#:limits @var{limits}]

Return a service that installs a configuration file for the
@uref{http://linux-pam.org/Linux-PAM-html/sag-pam_limits.html,
@code{pam_limits} module}.  The procedure optionally takes a list of
@code{pam-limits-entry} values, which can be used to specify
@code{ulimit} limits and nice priority limits to user sessions.

The following limits definition sets two hard and soft limits for all
login sessions of users in the @code{realtime} group:

@example
(pam-limits-service
 (list
  (pam-limits-entry "@@realtime" 'both 'rtprio 99)
  (pam-limits-entry "@@realtime" 'both 'memlock 'unlimited)))
@end example

The first entry increases the maximum realtime priority for
non-privileged processes; the second entry lifts any restriction of the
maximum address space that can be locked in memory.  These settings are
commonly used for real-time audio systems.
@end deffn


@node Scheduled Job Execution
@subsubsection Scheduled Job Execution


M gnu/services/base.scm => gnu/services/base.scm +43 -0
@@ 5,6 5,7 @@
;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
;;; Copyright © 2016 David Craven <david@craven.ch>
;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 100,6 101,8 @@
            urandom-seed-service
            rngd-service-type
            rngd-service
            pam-limits-service-type
            pam-limits-service

            %base-services))



@@ 924,6 927,46 @@ settings.
information on the configuration file syntax."
  (service syslog-service-type config-file))

(define pam-limits-service-type
  (let ((security-limits
         ;; Create /etc/security containing the provided "limits.conf" file.
         (lambda (limits-file)
           `(("security"
              ,(computed-file
                "security"
                #~(begin
                    (mkdir #$output)
                    (stat #$limits-file)
                    (symlink #$limits-file
                             (string-append #$output "/limits.conf"))))))))
        (pam-extension
         (lambda (pam)
           (let ((pam-limits (pam-entry
                              (control "required")
                              (module "pam_limits.so")
                              (arguments '("conf=/etc/security/limits.conf")))))
             (if (member (pam-service-name pam)
                         '("login" "su" "slim"))
                 (pam-service
                  (inherit pam)
                  (session (cons pam-limits
                                 (pam-service-session pam))))
                 pam)))))
    (service-type
     (name 'limits)
     (extensions
      (list (service-extension etc-service-type security-limits)
            (service-extension pam-root-service-type
                               (lambda _ (list pam-extension))))))))

(define* (pam-limits-service #:optional (limits '()))
  "Return a service that makes selected programs respect the list of
pam-limits-entry specified in LIMITS via pam_limits.so."
  (service pam-limits-service-type
           (plain-file "limits.conf"
                       (string-join (map pam-limits-entry->string limits)
                                    "\n"))))


;;;
;;; Guix services.

M gnu/system/pam.scm => gnu/system/pam.scm +61 -0
@@ 23,6 23,7 @@
  #:use-module (gnu services)
  #:use-module (ice-9 match)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-9)
  #:use-module (srfi srfi-11)
  #:use-module (srfi srfi-26)
  #:use-module ((guix utils) #:select (%current-system))


@@ 38,6 39,13 @@
            pam-entry-module
            pam-entry-arguments

            pam-limits-entry
            pam-limits-entry-domain
            pam-limits-entry-type
            pam-limits-entry-item
            pam-limits-entry-value
            pam-limits-entry->string

            pam-services->directory
            unix-pam-service
            base-pam-services


@@ 76,6 84,59 @@
  (arguments  pam-entry-arguments        ; list of string-valued g-expressions
              (default '())))

;; PAM limits entries are used by the pam_limits PAM module to set or override
;; limits on system resources for user sessions.  The format is specified
;; here: http://linux-pam.org/Linux-PAM-html/sag-pam_limits.html
(define-record-type <pam-limits-entry>
  (make-pam-limits-entry domain type item value)
  pam-limits-entry?
  (domain     pam-limits-entry-domain)   ; string
  (type       pam-limits-entry-type)     ; symbol
  (item       pam-limits-entry-item)     ; symbol
  (value      pam-limits-entry-value))   ; symbol or number

(define (pam-limits-entry domain type item value)
  "Construct a pam-limits-entry ensuring that the provided values are valid."
  (define (valid? value)
    (case item
      ((priority) (number? value))
      ((nice)     (and (number? value)
                       (>= value -20)
                       (<= value 19)))
      (else       (or (and (number? value)
                           (>= value -1))
                      (member value '(unlimited infinity))))))
  (define items
    (list 'core      'data       'fsize
          'memlock   'nofile     'rss
          'stack     'cpu        'nproc
          'as        'maxlogins  'maxsyslogins
          'priority  'locks      'sigpending
          'msgqueue  'nice       'rtprio))
  (when (not (member type '(hard soft both)))
    (error "invalid limit type" type))
  (when (not (member item items))
    (error "invalid limit item" item))
  (when (not (valid? value))
    (error "invalid limit value" value))
  (make-pam-limits-entry domain type item value))

(define (pam-limits-entry->string entry)
  "Convert a pam-limits-entry record to a string."
  (match entry
    (($ <pam-limits-entry> domain type item value)
     (string-join (list domain
                        (if (eq? type 'both)
                            "-"
                            (symbol->string type))
                        (symbol->string item)
                        (cond
                         ((symbol? value)
                          (symbol->string value))
                         (else
                          (number->string value))))
                  "	"))))

(define (pam-service->configuration service)
  "Return the derivation building the configuration file for SERVICE, to be
dumped in /etc/pam.d/NAME, where NAME is the name of SERVICE."