def test_ioctls_limit(self): fd = os.open("/dev/null", os.O_RDONLY) cap.enter() self.assertTrue(cap.sandboxed()) cap.ioctls_limit(fd, cap.Ioctls({termios.FIONREAD})) try: py_fcntl.ioctl(fd, termios.FIONREAD) except EnvironmentError as ee: # ENOTTY is fine, we're sending a stupid ioctl to a device # that doesn't know about it. The point is that capsicum # permitted it. if ee.errno != errno.ENOTTY: raise # Capsicum rejects ioctls outside the set we've limited # ourselves to above. with self.assertRaises(EnvironmentError) as cm: py_fcntl.ioctl(fd, termios.TIOCGETD) self.assertEqual(cm.exception.errno, cap.ENOTCAPABLE) # Capsicum rejects requests to increase privileges: with self.assertRaises(EnvironmentError) as cm: cap.ioctls_limit(fd, cap.Ioctls({termios.FIONREAD, termios.TIOCGETD})) self.assertEqual(cm.exception.errno, cap.ENOTCAPABLE) self.assertItemsEqual(cap.Ioctls(fd)._ioctls, [termios.FIONREAD])
def test_openat(self): fd = os.open("/dev", os.O_RDONLY) cap.enter() self.assertTrue(cap.sandboxed()) rightset = { cap.READ, # to allow the openat(O_RDONLY) cap.LOOKUP, # Also for openat() cap.FSTAT, # Used by Python os.fdopen(), although non-fatal if # denied. Attempts the syscall twice if denied, # though. cap.FCNTL, # Used by Python os.fdopen() for F_GETFL. Fatal if # denied. } cap.limit(fd, cap.Rights(rightset)) # Since we permit fcntl(), restrict the set of valid fcntls. cap.fcntls_limit(fd, cap.Fcntls({cap.fcntl.GETFL})) # Ordinary open is not permitted in sandbox mode: with self.assertRaises(EnvironmentError) as cm: open("/dev/null") self.assertEqual(cm.exception.errno, cap.ECAPMODE) # But with at least the privileges granted above, we can openat() and # read() from a file-like object: f = cap.openat(fd, "null", os.O_RDONLY) f.readlines()
def test_limit_trivial(self): fd = os.open("/dev/zero", os.O_RDONLY) cap.enter() self.assertTrue(cap.sandboxed()) # Unrestricted fds have full privileges after entering the # sandbox: os.read(fd, 1) # After removing all privileges (principally, CAP_READ), # read() is no longer permitted in sandbox mode: cap.limit(fd, cap.right.NONE) with self.assertRaises(EnvironmentError) as cm: os.read(fd, 1) self.assertEqual(cm.exception.errno, cap.ENOTCAPABLE)
def test_fcntls_limit_trivial(self): fd = os.open("/dev/null", os.O_RDONLY) cap.fcntls_limit(fd, cap.Fcntls([cap.fcntl.ALL])) cap.enter() self.assertTrue(cap.sandboxed()) # No-op, just verify no exception is raised. flags = py_fcntl.fcntl(fd, py_fcntl.F_GETFL) py_fcntl.fcntl(fd, py_fcntl.F_SETFL, flags) # Restrict to no fcntl rights and except NOTCAPABLE. cap.fcntls_limit(fd, cap.Fcntls()) with self.assertRaises(EnvironmentError) as cm: py_fcntl.fcntl(fd, py_fcntl.F_GETFL) self.assertEqual(cm.exception.errno, cap.ENOTCAPABLE)
def test_sandbox_trivial(self): self.assertFalse(cap.sandboxed()) cap.enter() self.assertTrue(cap.sandboxed())