xref: /unit/src/nxt_capability.c (revision 1489:4a3ec07f4b19)
11182St.nateldemoura@f5.com /*
21182St.nateldemoura@f5.com  * Copyright (C) Igor Sysoev
31182St.nateldemoura@f5.com  * Copyright (C) NGINX, Inc.
41182St.nateldemoura@f5.com  */
51182St.nateldemoura@f5.com 
61182St.nateldemoura@f5.com #include <nxt_main.h>
71182St.nateldemoura@f5.com 
81182St.nateldemoura@f5.com #if (NXT_HAVE_LINUX_CAPABILITY)
91182St.nateldemoura@f5.com 
101182St.nateldemoura@f5.com #include <linux/capability.h>
111182St.nateldemoura@f5.com #include <sys/syscall.h>
121182St.nateldemoura@f5.com 
131328St.nateldemoura@f5.com 
141328St.nateldemoura@f5.com #if (_LINUX_CAPABILITY_VERSION_3)
151328St.nateldemoura@f5.com #define NXT_CAPABILITY_VERSION  _LINUX_CAPABILITY_VERSION_3
161328St.nateldemoura@f5.com #elif (_LINUX_CAPABILITY_VERSION_2)
171328St.nateldemoura@f5.com #define NXT_CAPABILITY_VERSION  _LINUX_CAPABILITY_VERSION_2
181328St.nateldemoura@f5.com #else
191328St.nateldemoura@f5.com #define NXT_CAPABILITY_VERSION  _LINUX_CAPABILITY_VERSION
201328St.nateldemoura@f5.com #endif
211328St.nateldemoura@f5.com 
221328St.nateldemoura@f5.com 
231182St.nateldemoura@f5.com #define nxt_capget(hdrp, datap)                                               \
241182St.nateldemoura@f5.com             syscall(SYS_capget, hdrp, datap)
251182St.nateldemoura@f5.com #define nxt_capset(hdrp, datap)                                               \
261182St.nateldemoura@f5.com             syscall(SYS_capset, hdrp, datap)
271182St.nateldemoura@f5.com 
281182St.nateldemoura@f5.com #endif /* NXT_HAVE_LINUX_CAPABILITY */
291182St.nateldemoura@f5.com 
301182St.nateldemoura@f5.com 
311182St.nateldemoura@f5.com static nxt_int_t nxt_capability_specific_set(nxt_task_t *task,
321182St.nateldemoura@f5.com     nxt_capabilities_t *cap);
331182St.nateldemoura@f5.com 
341182St.nateldemoura@f5.com 
351182St.nateldemoura@f5.com nxt_int_t
nxt_capability_set(nxt_task_t * task,nxt_capabilities_t * cap)361182St.nateldemoura@f5.com nxt_capability_set(nxt_task_t *task, nxt_capabilities_t *cap)
371182St.nateldemoura@f5.com {
381182St.nateldemoura@f5.com     nxt_assert(cap->setid == 0);
391182St.nateldemoura@f5.com 
401182St.nateldemoura@f5.com     if (geteuid() == 0) {
411182St.nateldemoura@f5.com         cap->setid = 1;
42*1489St.nateldemoura@f5.com         cap->chroot = 1;
431182St.nateldemoura@f5.com         return NXT_OK;
441182St.nateldemoura@f5.com     }
451182St.nateldemoura@f5.com 
461182St.nateldemoura@f5.com     return nxt_capability_specific_set(task, cap);
471182St.nateldemoura@f5.com }
481182St.nateldemoura@f5.com 
491182St.nateldemoura@f5.com 
501182St.nateldemoura@f5.com #if (NXT_HAVE_LINUX_CAPABILITY)
511182St.nateldemoura@f5.com 
521182St.nateldemoura@f5.com static uint32_t
nxt_capability_linux_get_version()531182St.nateldemoura@f5.com nxt_capability_linux_get_version()
541182St.nateldemoura@f5.com {
551182St.nateldemoura@f5.com     struct __user_cap_header_struct hdr;
561182St.nateldemoura@f5.com 
571328St.nateldemoura@f5.com     hdr.version = NXT_CAPABILITY_VERSION;
581182St.nateldemoura@f5.com     hdr.pid     = nxt_pid;
591182St.nateldemoura@f5.com 
601182St.nateldemoura@f5.com     nxt_capget(&hdr, NULL);
611182St.nateldemoura@f5.com     return hdr.version;
621182St.nateldemoura@f5.com }
631182St.nateldemoura@f5.com 
641182St.nateldemoura@f5.com 
651182St.nateldemoura@f5.com static nxt_int_t
nxt_capability_specific_set(nxt_task_t * task,nxt_capabilities_t * cap)661182St.nateldemoura@f5.com nxt_capability_specific_set(nxt_task_t *task, nxt_capabilities_t *cap)
671182St.nateldemoura@f5.com {
681182St.nateldemoura@f5.com     struct __user_cap_data_struct    *val, data[2];
691182St.nateldemoura@f5.com     struct __user_cap_header_struct  hdr;
701182St.nateldemoura@f5.com 
711182St.nateldemoura@f5.com     /*
721182St.nateldemoura@f5.com      * Linux capability v1 fills an u32 struct.
731182St.nateldemoura@f5.com      * Linux capability v2 and v3 fills an u64 struct.
741182St.nateldemoura@f5.com      * We allocate data[2] for compatibility, we waste 4 bytes on v1.
751182St.nateldemoura@f5.com      *
761182St.nateldemoura@f5.com      * This is safe as we only need to check CAP_SETUID and CAP_SETGID
771182St.nateldemoura@f5.com      * that resides in the first 32-bit chunk.
781182St.nateldemoura@f5.com      */
791182St.nateldemoura@f5.com 
801182St.nateldemoura@f5.com     val = &data[0];
811182St.nateldemoura@f5.com 
821182St.nateldemoura@f5.com     /*
831182St.nateldemoura@f5.com      * Ask the kernel the preferred capability version
841182St.nateldemoura@f5.com      * instead of using _LINUX_CAPABILITY_VERSION from header.
851182St.nateldemoura@f5.com      * This is safer when distributing a pre-compiled Unit binary.
861182St.nateldemoura@f5.com      */
871182St.nateldemoura@f5.com     hdr.version = nxt_capability_linux_get_version();
881182St.nateldemoura@f5.com     hdr.pid = nxt_pid;
891182St.nateldemoura@f5.com 
901182St.nateldemoura@f5.com     if (nxt_slow_path(nxt_capget(&hdr, val) == -1)) {
911182St.nateldemoura@f5.com         nxt_alert(task, "failed to get process capabilities: %E", nxt_errno);
921182St.nateldemoura@f5.com         return NXT_ERROR;
931182St.nateldemoura@f5.com     }
941182St.nateldemoura@f5.com 
95*1489St.nateldemoura@f5.com     if ((val->effective & (1 << CAP_SYS_CHROOT)) != 0) {
96*1489St.nateldemoura@f5.com         cap->chroot = 1;
97*1489St.nateldemoura@f5.com     }
98*1489St.nateldemoura@f5.com 
991182St.nateldemoura@f5.com     if ((val->effective & (1 << CAP_SETUID)) == 0) {
1001182St.nateldemoura@f5.com         return NXT_OK;
1011182St.nateldemoura@f5.com     }
1021182St.nateldemoura@f5.com 
1031182St.nateldemoura@f5.com     if ((val->effective & (1 << CAP_SETGID)) == 0) {
1041182St.nateldemoura@f5.com         return NXT_OK;
1051182St.nateldemoura@f5.com     }
1061182St.nateldemoura@f5.com 
1071182St.nateldemoura@f5.com     cap->setid = 1;
1081182St.nateldemoura@f5.com     return NXT_OK;
1091182St.nateldemoura@f5.com }
1101182St.nateldemoura@f5.com 
1111182St.nateldemoura@f5.com #else
1121182St.nateldemoura@f5.com 
1131182St.nateldemoura@f5.com static nxt_int_t
nxt_capability_specific_set(nxt_task_t * task,nxt_capabilities_t * cap)1141182St.nateldemoura@f5.com nxt_capability_specific_set(nxt_task_t *task, nxt_capabilities_t *cap)
1151182St.nateldemoura@f5.com {
1161182St.nateldemoura@f5.com     return NXT_OK;
1171182St.nateldemoura@f5.com }
1181182St.nateldemoura@f5.com 
1191182St.nateldemoura@f5.com #endif
120