As I mentioned in the last message, I want to run ntpd as a separate ntp
user/group with only the necessary privileges.

To achieve this, I had to make a couple of changes:

* Add a new ntp user and group to /etc/passwd and /etc/group.  This will
  probably have to be handled via the OS/Net consolidation, since SUNWntp*
  will be part of the base system.  It would be nicest to use uid/gid 123 :-),
  but I think uids > 100 are reserved for the user.  I have no idea how
  such new daemon uid's/gid's are allocated.

* I changed /var/ntp, /var/ntp/ntpstats to use that uid/gid.  This needs to
  be done during an upgrade, too.  (Actually, I only did this after the
  initial privilege debugging step.)

* After that, I modified the ntp SMF manifest to run the start method as
  user ntp, but with all privileges, and used Darren Moffat's privdebug
  script to investigate the privileges used.  At first, I had to modify
  ntpd.c to remove the check for uid 0 (Bug 644) so ntpd runs as non-root
  at all.

  Here's what I found:

  ntpd:    file_dac_write       for /var/ntp/ntp.drift, ntpstats/* (were
                                owned by root:sys before)
           net_privaddr         for bind to port 123
           proc_fork            resolving process (in basic set)
           proc_exec            for method script (in basic set)
           proc_lock_memory     for memcntl
           sys_net_config       strange udp-internal use, see below
           sys_time             for ntp_adjtime

  ntpdate: net_privaddr         for bind to port 123
           proc_priocntl        for setpriority

  file_dac_write is unnecessary when /var/ntp and below properly belong to
  ntp:ntp, so they can be dropped.

  net_privaddr may perhaps be dropped (at least temporarily) after startup,
  though it will be needed later with runtime configuration.

  proc_exec should be dropped by ntpd after startup, and may become
  unnecessary if we can avoid the method script alltogether and just start
  ntpd directly.

  proc_lock_memory (used by mlockall) can be dropped after startup as well.

  sys_net_config was strange: at first I thought it was needed for sendto
  with a source port of 123, although net_privaddr should handle that.  I
  had modified privdebug to include a ustack() so I could see at what point
  in the user code the privilege was needed.  Inspection of the kernel
  code revealed that it is used in udp.c (udp_bind_hash_report and
  udp_status_report).  I doesn't seem to be necessary for ntpd to run
  successfully, so the privdebug output can be confusing and result in too
  many privileges being granted.  I'll probably report this to Darren.

  sys_time is obviously needed for ntp_adjtime and cannot be dropped at all

  ntpdate needs proc_priocntl additionaly, due to its use of setpriority.
  ntpd would need it as well if invoked with -N.

  Apart from that, some privileges from the basic set aren't needed and
  should thus be dropped: file_link_any, proc_info, proc_session.

So here's the relevant section of the modified ntp SMF manifest:

        <exec_method
            type='method'
            name='start'
            exec='/lib/svc/method/ntp'
            timeout_seconds='1800' >
                <method_context>
                <!--
                        privileges: from the basic set, only proc_fork and
                        proc_exec need to be retained so the method script
                        can run.
                        net_privaddr is necessary to bind to privileged
                        port 123, proc_lock_memory is needed for mlockall,
                        sys_time is of course necessary for ntp_adjtime,
                        proc_priocntl is needed by ntpdate (setpriority)
                -->
                        <method_credential
                            user='ntp'
                            group='ntp'
                            
privileges='basic,!file_link_any,!proc_info,!proc_session,net_privaddr,proc_lock_memory,sys_time,proc_priocntl'
 />
                </method_context>
        </exec_method>

We need three groups of code changes to ntpd, though:

* Checking for <sys/priv.h> and allowing the daemon to run as non-root at
  all (which is currently avoided by a hack to #if 0 the check in ntpd.c).

* Dropping all privileges which are only needed during startup after the
  daemon is up.

* Temporarily dropping net_privaddr while it isn't needed.

I'll go for the first group initially and implement more (perhaps for
ntp-dev) as time permits.

        Rainer

-----------------------------------------------------------------------------
Rainer Orth, Faculty of Technology, Bielefeld University

Reply via email to