OpenBSD Journal

Status of pledge(2)

Contributed by tj on from the cutting-pledge-of-development dept.

For those wondering about the ongoing integration progress of OpenBSD's pledge(2) subsystem, Theo de Raadt (deraadt@) has an informative update.

Our base system contains 600 ELF binaries, which are found in
the directories /bin /sbin /usr/bin /usr/sbin and /usr/libexec.

368 have been converted to use pledge in some form -- generally
the application of pledge is quite strong.  This is that list:

  [ ac acpidump addr2line apm apply apropos ar arp as at atq atrm awk
  b64decode b64encode banner basename batch bc bgpctl bgpd biff c++
  c++filt cal cap_mkdb captoinfo cat cc chgrp chmod chown ci cksum clear
  clri cmp co col colrm column comm compress comsat config cp cpio cpp
  cron crontab crunchgen csh csplit ctags cu cut date dc dd deroff
  dev_mkdb df diff diff3prog dig dirname disklabel dmesg doas du
  dvmrpctl echo ed egrep eigrpctl eigrpd encrypt env ex expand expr
  fdisk fgen fgrep file find finger fingerd flex flex++ fmt fold from
  fsck_ext2fs fsck_ffs fsck_msdos fsdb fsirand fstat ftp ftpd fuser g++
  gcc gencat getcap getent getopt getty grep group groupadd groupdel
  groupinfo groupmod groups gunzip gzcat gzip head help hexdump host
  htpasswd httpd id ident identd ikectl iked indent inetd info infocmp
  infokey infotocap install-info iscsictl join jot kdump kill ksh
  kvm_mkdb lam last lastcomm ld ldapctl ldapd ldconfig ldpctl ldpd leave
  less lesskey lex ln lndir locate locate.bigram locate.code lock
  lockspool logger login_activ login_crypto login_passwd login_reject
  login_skey login_snk login_tis login_token login_yubikey logname look
  ls m4 mailwrapper make makeinfo makewhatis makewhatis man mandoc md5
  merge mesg mg mkdir mklocale mktemp more nc ncheck ncheck_ffs
  netgroup_mkdb nice nl nm nohup nologin nslookup ntpctl ntpd objcopy
  objdump od opencvs openssl ospf6ctl ospfctl ospfd otp-md5 otp-rmd160
  otp-sha1 paste patch pax pflogd pgrep ping ping6 pkill portmap pr
  printenv printf ps pwd pwd_mkdb radiusctl radiusd radiusd_bsdauth
  radiusd_radius ranlib rarpd rcs rcsclean rcsdiff rcsmerge rdate
  readelf readlink rebound relayctl relayd renice reset rev ripctl rksh
  rlog rm rmdir rmt route route6d rpcgen rs rtadvd savecore scan_ffs scp
  script sdiff sed sendbug sftp sh sha1 sha256 sha512 signify size skey
  skeyaudit skeyinfo sleep slowcgi smtpctl smtpd snmpctl sort spamdb
  spellprog split sshd stat strings strip stty su syslogc syslogd
  systrace tail tar tcpbench tcpdump tee telnet test texindex tftp
  tftp-proxy tftpd tic time tmux top touch tput tr traceroute
  traceroute6 tradcpp tset tsort tty tunefs ul uname uncompress unexpand
  unifdef uniq units unvis uptime user useradd userdel userinfo usermod
  users uudecode uuencode vi view vipw vis w wall wc what whatis whereis
  which who whoami whois write x99token xargs yacc yes ypcat ypldap zcat
  zdump zegrep zfgrep zgrep zic zzz ZZZ
  
These are the programs which have not yet been pledged, but are
plausible:

  Mail a2p accton amd amq apmd atactl aucat audioctl authpf authpf-noip
  badsect bgplgsh bioctl calendar cdio chat chfn chio chpass chsh cvs
  dhclient dhcpd dhcrelay dump dumpfs dvmrpd edquota eject fdformat fsck
  ftp-proxy gcov gdb getconf gpioctl gprof growfs hostapd hotplugd
  ifconfig ifstated init installboot iostat ipcs ipsecctl isakmpd iscsid
  kbd keynote kgmon ldattach locale login login_chpass login_lchpass
  login_radius lpc lpf lpq lpr lprm lptest mail mail.local mailx makedbm
  makemap map-mbone memconfig midiplay mixerctl mkalias mkhybrid mknetid
  mopa.out mopchk mopd mopprobe moptrace mount mountd mrinfo mrouted
  mtrace mtree mv ndp netstat newfs newfs_ext2fs newfs_msdos newsyslog
  nfsd nfsstat npppctl npppd nsd nsd-checkconf nsd-checkzone nsd-control
  ntalkd ospf6d pac passwd pcidump pppstats procmap pstat quot quota
  quotacheck quotaoff quotaon radioctl rbootd rdist rdistd rdump
  repquota restore revnetgroup ripd rpc.bootparamd rpc.lockd rpc.rquotad
  rpc.rstatd rpc.rusersd rpc.rwalld rpc.statd rpc.yppasswdd rpcinfo
  rrestore rup rusers rwall sa sasyncd scsi sensorsd sftp-server
  showmount skeyinit sndiod snmpd spamd spamd-setup spamlogd sqlite3 ssh
  ssh-add ssh-agent ssh-keygen ssh-keyscan ssh-keysign ssh-pkcs11-helper
  stdethers stdhosts swapctl swapon sysctl systat table-ldap
  table-passwd table-sqlite talk trpt unbound unbound-anchor
  unbound-checkconf unbound-control unbound-host usbdevs usbhidaction
  usbhidctl vacation vmstat vnconfig watchdogd wsconscfg wsconsctl
  wsfontload wsmoused ypbind ypmatch yppoll yppush ypserv ypset yptest
  ypwhich ypxfr

I'm not listing the ones we won't pledge because they are too simple
(like true, hostname..) or can't pledge (because their last operation
is a crazy system call like "reboot" or "mount"), or uhm, perl itself.

66% pledged...

More fine-grained syscall restriction in the base system is great news.

Not mentioned in this mail is the fact that some ports have even been patched too. The often-called-on-random-files decompression tools unzip, bzip2 and xz have been pledged to greatly reduce the possible damage they can do. Portions of the Xenocara base (cwm, xterm, some others) have also received the same treatment. It's a long process, but the end result should be pretty spectacular.

(Comments are closed)


Comments
  1. By Anonymous Coward (192.82.241.25) on

    Just in Theory:

    Ain't it possible to modify an Application at runtime to fake pledge-Statements made by the Application and thus gaining more priviledges required to do more evil?

    Sorry for the first try. My Browser did not send the Text

    Comments
    1. By Ruben (167.58.51.38) on

      > Just in Theory:
      >
      > Ain't it possible to modify an Application at runtime to fake pledge-Statements made by the Application and thus gaining more priviledges required to do more evil?
      >
      > Sorry for the first try. My Browser did not send the Text

      Pledged abilities can never be regained. So you must modify the stack before the pledge() call, which normally occurs in the initialization when the program has no interaction with users.

      Comments
      1. By Anonymous Coward (91.65.157.73) on

        > > Just in Theory:
        > >
        > > Ain't it possible to modify an Application at runtime to fake pledge-Statements made by the Application and thus gaining more priviledges required to do more evil?
        > >
        > > Sorry for the first try. My Browser did not send the Text
        >
        > Pledged abilities can never be regained. So you must modify the stack before the pledge() call, which normally occurs in the initialization when the program has no interaction with users.

        Would it be possible with stack based attacks?

        I understand it this way (simplyfied):

        1. Application gets compiled with support
        2. Application gets executed, "pledge"-options are at the Stack
        3. Exploiting the Application fails because the pledge-settings are read just once, at startup (so the Kernel has to hold a kind of "state"-table of any executed Application which it does not, at least I don't find anything about such a feature. Run "httpd" once, restart it -> Pledge-Settings wont get re-read except you reboot the OS. So a modified binary or anything else wont work.)

        If this aint true somebody could in Theory modify the stack. The only issue I see is a race condition. If I am aware where the stack will be and if I can (by any means) write into this addressspace I could modify the pledge settings the Application requests, or?

        This is just a wild Idea but this could be a problem for applications/the idea of pledge or?

        To counter this the Kernel needs to hold a "state table" (if I can modify the list it's a kernel exploit anyway).

        Comments
        1. By Anonymous Coward (87.8.40.74) on

          > > > Just in Theory:
          > > >
          > > > Ain't it possible to modify an Application at runtime to fake pledge-Statements made by the Application and thus gaining more priviledges required to do more evil?
          > > >
          > > > Sorry for the first try. My Browser did not send the Text
          > >
          > > Pledged abilities can never be regained. So you must modify the stack before the pledge() call, which normally occurs in the initialization when the program has no interaction with users.
          >
          > Would it be possible with stack based attacks?
          >
          > I understand it this way (simplyfied):
          >
          > 1. Application gets compiled with support
          > 2. Application gets executed, "pledge"-options are at the Stack
          > 3. Exploiting the Application fails because the pledge-settings are read just once, at startup (so the Kernel has to hold a kind of "state"-table of any executed Application which it does not, at least I don't find anything about such a feature. Run "httpd" once, restart it -> Pledge-Settings wont get re-read except you reboot the OS. So a modified binary or anything else wont work.)
          >
          > If this aint true somebody could in Theory modify the stack. The only issue I see is a race condition. If I am aware where the stack will be and if I can (by any means) write into this addressspace I could modify the pledge settings the Application requests, or?
          >
          > This is just a wild Idea but this could be a problem for applications/the idea of pledge or?
          >
          > To counter this the Kernel needs to hold a "state table" (if I can modify the list it's a kernel exploit anyway).

          The kernel DOES hold it :)
          Start by looking at the original tame diff,
          https://marc.info/?l=openbsd-tech&m=143725996614627&w=2
          - look at struct process in sys/proc.h, then look at what happens eg before tame_fail is called... the current version is not that different.

  2. By Anonymous Coward (95.92.39.189) on

    Can anyone explain what exactly is pledge(2)?

    Comments
    1. By Anonymous Coward (87.8.40.74) on

      > Can anyone explain what exactly is pledge(2)?

      http://www.openbsd.org/papers/hackfest2015-pledge/mgp00001.html

  3. By Jorden Verwer (83.86.183.38) on

    On a related note, I noticed that true (previously a shell script) was replaced by a version written in C. The code is trivial, of course, but it could be made even simpler. It doesn't need any C code, or any code at all, for that matter. A simple 0-byte executable file will do the trick. It's the only program that will fit in 0 bytes (and of course, by definition only one program can). ;)

    Comments
    1. By phessler (phessler) on http://www.openbsdfoundation.org/donations.html

      > On a related note, I noticed that true (previously a shell script) was replaced by a version written in C. The code is trivial, of course, but it could be made even simpler. It doesn't need any C code, or any code at all, for that matter. A simple 0-byte executable file will do the trick. It's the only program that will fit in 0 bytes (and of course, by definition only one program can). ;)

      that's not true(1)

      Comments
      1. By Jorden Verwer (84.105.157.249) on

        > > On a related note, I noticed that true (previously a shell script) was replaced by a version written in C. The code is trivial, of course, but it could be made even simpler. It doesn't need any C code, or any code at all, for that matter. A simple 0-byte executable file will do the trick. It's the only program that will fit in 0 bytes (and of course, by definition only one program can). ;)
        >
        > that's not true(1)

        AMD64, OpenBSD 5.8, default installation, logged in as root, working from any of sh, csh and ksh. For me a zero-byte file does the exact same thing as /usr/bin/true on such a system. Of course you need to chmod +x the file first, but that's elementary...

        Comments
        1. By Theo de Raadt (199.185.136.55) on

          > > > On a related note, I noticed that true (previously a shell script) was replaced by a version written in C. The code is trivial, of course, but it could be made even simpler. It doesn't need any C code, or any code at all, for that matter. A simple 0-byte executable file will do the trick. It's the only program that will fit in 0 bytes (and of course, by definition only one program can). ;)
          > >
          > > that's not true(1)
          >
          > AMD64, OpenBSD 5.8, default installation, logged in as root, working from any of sh, csh and ksh. For me a zero-byte file does the exact same thing as /usr/bin/true on such a system. Of course you need to chmod +x the file first, but that's elementary...

          Which result in 83 system calls being called. About a 1/3 of those are needed for the crt0 static PIE setup, but the rest is extra -- including stat()'s along the path, signal and process group setup. All that because "" is up a full sh.

          You call that the "exact same thing"? No, you mean "the exact same final result". The underlying action is not the same at all, and since it has started a demand-paged 500K shell, I'd say your idea of "simple" is out of whack.

          What you propose is also slower. Not that it matters; that is about as relevant as your metric..

          Comments
          1. By Jorden Verwer (83.86.183.38) on

            > > > > On a related note, I noticed that true (previously a shell script) was replaced by a version written in C. The code is trivial, of course, but it could be made even simpler. It doesn't need any C code, or any code at all, for that matter. A simple 0-byte executable file will do the trick. It's the only program that will fit in 0 bytes (and of course, by definition only one program can). ;)
            > > >
            > > > that's not true(1)
            > >
            > > AMD64, OpenBSD 5.8, default installation, logged in as root, working from any of sh, csh and ksh. For me a zero-byte file does the exact same thing as /usr/bin/true on such a system. Of course you need to chmod +x the file first, but that's elementary...
            >
            > Which result in 83 system calls being called. About a 1/3 of those are needed for the crt0 static PIE setup, but the rest is extra -- including stat()'s along the path, signal and process group setup. All that because "" is up a full sh.
            >
            > You call that the "exact same thing"? No, you mean "the exact same final result". The underlying action is not the same at all, and since it has started a demand-paged 500K shell, I'd say your idea of "simple" is out of whack.
            >
            > What you propose is also slower. Not that it matters; that is about as relevant as your metric..
            >
            >

            Well yeah, it's basically the optimized version of the shell script that was used up to and including OpenBSD 5.8, meaning it does the exact same thing as /usr/bin/true from OpenBSD 5.8, but without any actual code.

            I'm not really proposing that OpenBSD should switch to the 0-byte true, although I could've stated that more clearly. I just wanted to mention the possibility, because I think a 0-byte program is an interesting idea from a conceptual point of view. It's also fun that it just works.

            If it were possible to write both true and false as 1-byte programs, I might advocate that, but as it stands I think the asymmetry is too confusing and on the whole this curiosity isn't worth the trouble that would be caused by actually making it part of OpenBSD.

            Anyway, thank you for explaining your rationale for switching true and false to C. I couldn't find anything about it on any of the mailing lists, but didn't want to bother people by asking about it specifically. Your commit message wasn't totally clear to me, but now I know your reasoning behind the change. I agree that it makes very little difference either way, but this is the right thing to do. Small improvements are improvements too.

Latest Articles

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]