sysdeputil.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:31k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * sysdeputil.c
  6.  *
  7.  * Highly system dependent utilities - e.g. authentication, capabilities.
  8.  */
  9. #include "sysdeputil.h"
  10. #include "str.h"
  11. #include "sysutil.h"
  12. #include "utility.h"
  13. #include "secbuf.h"
  14. #include "defs.h"
  15. #include "tunables.h"
  16. #include "builddefs.h"
  17. /* For Linux, this adds nothing :-) */
  18. #include "port/porting_junk.h"
  19. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3)
  20.   #define _FILE_OFFSET_BITS 64
  21.   #define _LARGEFILE_SOURCE 1
  22.   #define _LARGEFILE64_SOURCE 1
  23. #endif
  24. /* For INT_MAX */
  25. #include <limits.h>
  26. /* For fd passing */
  27. #include <sys/types.h>
  28. #include <sys/socket.h>
  29. /* For FreeBSD */
  30. #include <sys/param.h>
  31. #include <sys/uio.h>
  32. #include <sys/prctl.h>
  33. #include <signal.h>
  34. /* Configuration.. here are the possibilities */
  35. #undef VSF_SYSDEP_HAVE_CAPABILITIES
  36. #undef VSF_SYSDEP_HAVE_SETKEEPCAPS
  37. #undef VSF_SYSDEP_HAVE_SETPDEATHSIG
  38. #undef VSF_SYSDEP_HAVE_LINUX_SENDFILE
  39. #undef VSF_SYSDEP_HAVE_FREEBSD_SENDFILE
  40. #undef VSF_SYSDEP_HAVE_HPUX_SENDFILE
  41. #undef VSF_SYSDEP_HAVE_AIX_SENDFILE
  42. #undef VSF_SYSDEP_HAVE_SETPROCTITLE
  43. #undef VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK
  44. #undef VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE
  45. #undef VSF_SYSDEP_HAVE_MAP_ANON
  46. #undef VSF_SYSDEP_NEED_OLD_FD_PASSING
  47. #undef VSF_SYSDEP_HAVE_LINUX_CLONE
  48. #ifdef VSF_BUILD_PAM
  49.   #define VSF_SYSDEP_HAVE_PAM
  50. #endif
  51. #define VSF_SYSDEP_HAVE_SHADOW
  52. #define VSF_SYSDEP_HAVE_USERSHELL
  53. #define VSF_SYSDEP_HAVE_LIBCAP
  54. #define VSF_SYSDEP_HAVE_UTMPX
  55. #define __USE_GNU
  56. #include <utmpx.h>
  57. /* BEGIN config */
  58. #if defined(__linux__)
  59.   #include <errno.h>
  60.   #include <syscall.h>
  61.   #define VSF_SYSDEP_HAVE_LINUX_CLONE
  62.   #include <sched.h>
  63.   #ifndef CLONE_NEWPID
  64.     #define CLONE_NEWPID 0x20000000
  65.   #endif
  66.   #ifndef CLONE_NEWIPC
  67.     #define CLONE_NEWIPC 0x08000000
  68.   #endif
  69.   #ifndef CLONE_NEWNET
  70.     #define CLONE_NEWNET 0x40000000
  71.   #endif
  72.   #include <linux/unistd.h>
  73.   #include <errno.h>
  74.   #include <syscall.h>
  75. #endif
  76. #if defined(__linux__) && !defined(__ia64__) && !defined(__s390__)
  77.   #define VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK
  78.   #include <linux/version.h>
  79.   #if defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION)
  80.     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))
  81.       #define VSF_SYSDEP_HAVE_CAPABILITIES
  82.       #define VSF_SYSDEP_HAVE_LINUX_SENDFILE
  83.       #ifdef PR_SET_KEEPCAPS
  84.         #define VSF_SYSDEP_HAVE_SETKEEPCAPS
  85.       #endif
  86.       #ifdef PR_SET_PDEATHSIG
  87.         #define VSF_SYSDEP_HAVE_SETPDEATHSIG
  88.       #endif
  89.     #endif
  90.   #endif
  91. #endif
  92. #if (defined(__FreeBSD__) && __FreeBSD__ >= 3)
  93.   #define VSF_SYSDEP_HAVE_FREEBSD_SENDFILE
  94.   #define VSF_SYSDEP_HAVE_SETPROCTITLE
  95. #endif
  96. #if defined(__NetBSD__)
  97.   #include <stdlib.h>
  98.   #define VSF_SYSDEP_HAVE_SETPROCTITLE
  99.   #include <sys/param.h>
  100.   #if __NetBSD_Version__ >= 106070000
  101.     #define WTMPX_FILE _PATH_WTMPX
  102.   #else
  103.     #undef VSF_SYSDEP_HAVE_UTMPX
  104.   #endif
  105. #endif
  106. #ifdef __hpux
  107.   #include <sys/socket.h>
  108.   #ifdef SF_DISCONNECT
  109.     #define VSF_SYSDEP_HAVE_HPUX_SENDFILE
  110.   #endif
  111.   #include <sys/param.h>
  112.   #include <sys/pstat.h>
  113.   #ifdef PSTAT_SETCMD
  114.     #define VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE
  115.   #endif
  116.   #undef VSF_SYSDEP_HAVE_UTMPX
  117. #endif
  118. #include <unistd.h>
  119. #include <sys/mman.h>
  120. #ifdef MAP_ANON
  121.   #define VSF_SYSDEP_HAVE_MAP_ANON
  122. #endif
  123. #ifdef __sgi
  124.   #undef VSF_SYSDEP_HAVE_USERSHELL
  125.   #undef VSF_SYSDEP_HAVE_LIBCAP
  126. #endif
  127. #ifdef _AIX
  128.   #undef VSF_SYSDEP_HAVE_USERSHELL
  129.   #undef VSF_SYSDEP_HAVE_LIBCAP
  130.   #undef VSF_SYSDEP_HAVE_UTMPX
  131.   #undef VSF_SYSDEP_HAVE_PAM
  132.   #undef VSF_SYSDEP_HAVE_SHADOW
  133.   #undef VSF_SYSDEP_HAVE_SETPROCTITLE
  134.   #define VSF_SYSDEP_HAVE_AIX_SENDFILE
  135.   #define VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK
  136.   #define VSF_SYSDEP_HAVE_MAP_ANON
  137. #endif
  138. #ifdef __osf__
  139.   #undef VSF_SYSDEP_HAVE_USERSHELL
  140. #endif
  141. #if (defined(__sgi) || defined(__hpux) || defined(__osf__))
  142.   #define VSF_SYSDEP_NEED_OLD_FD_PASSING
  143. #endif
  144. #ifdef __sun
  145.   #define VSF_SYSDEP_HAVE_SOLARIS_SENDFILE
  146. #endif
  147. /* END config */
  148. /* PAM support - we include our own dummy version if the system lacks this */
  149. #include <security/pam_appl.h>
  150. /* No PAM? Try getspnam() with a getpwnam() fallback */
  151. #ifndef VSF_SYSDEP_HAVE_PAM
  152. /* This may hit our own "dummy" include and undef VSF_SYSDEP_HAVE_SHADOW */
  153. #include <shadow.h>
  154. #include <pwd.h>
  155. #include <unistd.h>
  156. #include <crypt.h>
  157. #endif
  158. /* Prefer libcap based capabilities over raw syscall capabilities */
  159. #include <sys/capability.h>
  160. #if defined(VSF_SYSDEP_HAVE_CAPABILITIES) && !defined(VSF_SYSDEP_HAVE_LIBCAP)
  161. #include <linux/unistd.h>
  162. #include <linux/capability.h>
  163. #include <errno.h>
  164. #include <syscall.h>
  165. int capset(cap_user_header_t header, const cap_user_data_t data)
  166. {
  167.   return syscall(__NR_capset, header, data);
  168. }
  169. /* Gross HACK to avoid warnings - linux headers overlap glibc headers */
  170. #undef __NFDBITS
  171. #undef __FDMASK
  172. #endif /* VSF_SYSDEP_HAVE_CAPABILITIES */
  173. #if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || 
  174.     defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  175. #include <sys/sendfile.h>
  176. #elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE)
  177. #include <sys/types.h>
  178. #include <sys/socket.h>
  179. #elif defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE)
  180. #include <sys/socket.h>
  181. #else /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */
  182. #include <unistd.h>
  183. #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */
  184. #ifdef VSF_SYSDEP_HAVE_SETPROCTITLE
  185. #include <sys/types.h>
  186. #include <unistd.h>
  187. #endif
  188. #ifdef VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK
  189. extern char** environ;
  190. static unsigned int s_proctitle_space = 0;
  191. static int s_proctitle_inited = 0;
  192. static char* s_p_proctitle = 0;
  193. #endif
  194. #ifndef VSF_SYSDEP_HAVE_MAP_ANON
  195. #include <sys/types.h>
  196. #include <sys/stat.h>
  197. #include <fcntl.h>
  198. static int s_zero_fd = -1;
  199. #endif
  200. /* File private functions/variables */
  201. static int do_sendfile(const int out_fd, const int in_fd,
  202.                        unsigned int num_send, filesize_t start_pos);
  203. static void vsf_sysutil_setproctitle_internal(const char* p_text);
  204. static struct mystr s_proctitle_prefix_str;
  205. /* These two aren't static to avoid OpenBSD build warnings. */
  206. void vsf_insert_uwtmp(const struct mystr* p_user_str,
  207.                       const struct mystr* p_host_str);
  208. void vsf_remove_uwtmp(void);
  209. #ifndef VSF_SYSDEP_HAVE_PAM
  210. int
  211. vsf_sysdep_check_auth(struct mystr* p_user_str,
  212.                       const struct mystr* p_pass_str,
  213.                       const struct mystr* p_remote_host)
  214. {
  215.   const char* p_crypted;
  216.   const struct passwd* p_pwd = getpwnam(str_getbuf(p_user_str));
  217.   (void) p_remote_host;
  218.   if (p_pwd == NULL)
  219.   {
  220.     return 0;
  221.   }
  222.   #ifdef VSF_SYSDEP_HAVE_USERSHELL
  223.   if (tunable_check_shell)
  224.   {
  225.     const char* p_shell;
  226.     while ((p_shell = getusershell()) != NULL)
  227.     {
  228.       if (!vsf_sysutil_strcmp(p_shell, p_pwd->pw_shell))
  229.       {
  230.         break;
  231.       }
  232.     }
  233.     endusershell();
  234.     if (p_shell == NULL)
  235.     {
  236.       return 0;
  237.     }
  238.   }
  239.   #endif
  240.   #ifdef VSF_SYSDEP_HAVE_SHADOW
  241.   {
  242.     const struct spwd* p_spwd = getspnam(str_getbuf(p_user_str));
  243.     if (p_spwd != NULL)
  244.     {
  245.       long curr_time = vsf_sysutil_get_time_sec();
  246.       int days;
  247.       days = curr_time / (60 * 60 * 24);
  248.       if (p_spwd->sp_expire > 0 && p_spwd->sp_expire < days)
  249.       {
  250.         return 0;
  251.       }
  252.       if (p_spwd->sp_lstchg > 0 && p_spwd->sp_max > 0 &&
  253.           p_spwd->sp_lstchg + p_spwd->sp_max < days)
  254.       {
  255.         return 0;
  256.       }
  257.       p_crypted = crypt(str_getbuf(p_pass_str), p_spwd->sp_pwdp);
  258.       if (!vsf_sysutil_strcmp(p_crypted, p_spwd->sp_pwdp))
  259.       {
  260.         return 1;
  261.       }
  262.     }
  263.   }
  264.   #endif /* VSF_SYSDEP_HAVE_SHADOW */
  265.   p_crypted = crypt(str_getbuf(p_pass_str), p_pwd->pw_passwd);
  266.   if (!vsf_sysutil_strcmp(p_crypted, p_pwd->pw_passwd))
  267.   {
  268.     return 1;
  269.   }
  270.   return 0;
  271. }
  272. #else /* VSF_SYSDEP_HAVE_PAM */
  273. #if (defined(__sun) || defined(__hpux)) && 
  274.     !defined(LINUX_PAM) && !defined(_OPENPAM)
  275. /* Sun's PAM doesn't use const here, while Linux-PAM and OpenPAM do */
  276. #define lo_const
  277. #else
  278. #define lo_const const
  279. #endif
  280. typedef lo_const void* pam_item_t;
  281. static pam_handle_t* s_pamh;
  282. static struct mystr s_pword_str;
  283. static int pam_conv_func(int nmsg, const struct pam_message** p_msg,
  284.                          struct pam_response** p_reply, void* p_addata);
  285. static void vsf_auth_shutdown(void);
  286. int
  287. vsf_sysdep_check_auth(struct mystr* p_user_str,
  288.                       const struct mystr* p_pass_str,
  289.                       const struct mystr* p_remote_host)
  290. {
  291.   int retval;
  292.   pam_item_t item;
  293.   const char* pam_user_name = 0;
  294.   struct pam_conv the_conv =
  295.   {
  296.     &pam_conv_func,
  297.     0
  298.   };
  299.   if (s_pamh != 0)
  300.   {
  301.     bug("vsf_sysdep_check_auth");
  302.   }
  303.   str_copy(&s_pword_str, p_pass_str);
  304.   retval = pam_start(tunable_pam_service_name,
  305.                      str_getbuf(p_user_str), &the_conv, &s_pamh);
  306.   if (retval != PAM_SUCCESS)
  307.   {
  308.     s_pamh = 0;
  309.     return 0;
  310.   }
  311. #ifdef PAM_RHOST
  312.   retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host));
  313.   if (retval != PAM_SUCCESS)
  314.   {
  315.     (void) pam_end(s_pamh, retval);
  316.     s_pamh = 0;
  317.     return 0;
  318.   }
  319. #endif
  320. #ifdef PAM_TTY
  321.   retval = pam_set_item(s_pamh, PAM_TTY, "ftp");
  322.   if (retval != PAM_SUCCESS)
  323.   {
  324.     (void) pam_end(s_pamh, retval);
  325.     s_pamh = 0;
  326.     return 0;
  327.   }
  328. #endif
  329. #ifdef PAM_RUSER
  330.   retval = pam_set_item(s_pamh, PAM_RUSER, str_getbuf(p_user_str));
  331.   if (retval != PAM_SUCCESS)
  332.   {
  333.     (void) pam_end(s_pamh, retval);
  334.     s_pamh = 0;
  335.     return 0;
  336.   }
  337. #endif
  338.   retval = pam_authenticate(s_pamh, 0);
  339.   if (retval != PAM_SUCCESS)
  340.   {
  341.     (void) pam_end(s_pamh, retval);
  342.     s_pamh = 0;
  343.     return 0;
  344.   }
  345. #ifdef PAM_USER
  346.   retval = pam_get_item(s_pamh, PAM_USER, &item);
  347.   if (retval != PAM_SUCCESS)
  348.   {
  349.     (void) pam_end(s_pamh, retval);
  350.     s_pamh = 0;
  351.     return 0;
  352.   }
  353.   pam_user_name = item;
  354.   str_alloc_text(p_user_str, pam_user_name);
  355. #endif
  356.   retval = pam_acct_mgmt(s_pamh, 0);
  357.   if (retval != PAM_SUCCESS)
  358.   {
  359.     (void) pam_end(s_pamh, retval);
  360.     s_pamh = 0;
  361.     return 0;
  362.   }
  363.   retval = pam_setcred(s_pamh, PAM_ESTABLISH_CRED);
  364.   if (retval != PAM_SUCCESS)
  365.   {
  366.     (void) pam_end(s_pamh, retval);
  367.     s_pamh = 0;
  368.     return 0;
  369.   }
  370.   if (!tunable_session_support)
  371.   {
  372.     /* You're in already! */
  373.     (void) pam_end(s_pamh, retval);
  374.     s_pamh = 0;
  375.     return 1;
  376.   }
  377.   /* Must do this BEFORE opening a session for pam_limits to count us */
  378.   vsf_insert_uwtmp(p_user_str, p_remote_host);
  379.   retval = pam_open_session(s_pamh, 0);
  380.   if (retval != PAM_SUCCESS)
  381.   {
  382.     vsf_remove_uwtmp();
  383.     (void) pam_setcred(s_pamh, PAM_DELETE_CRED);
  384.     (void) pam_end(s_pamh, retval);
  385.     s_pamh = 0;
  386.     return 0;
  387.   }
  388.   /* We MUST ensure the PAM session, utmp, wtmp etc. are cleaned up, however
  389.    * we exit.
  390.    */
  391.   vsf_sysutil_set_exit_func(vsf_auth_shutdown);
  392.   /* You're in dude */
  393.   return 1;
  394. }
  395. static void
  396. vsf_auth_shutdown(void)
  397. {
  398.   if (s_pamh == 0)
  399.   {
  400.     bug("vsf_auth_shutdown");
  401.   }
  402.   (void) pam_close_session(s_pamh, 0);
  403.   (void) pam_setcred(s_pamh, PAM_DELETE_CRED);
  404.   (void) pam_end(s_pamh, PAM_SUCCESS);
  405.   s_pamh = 0;
  406.   vsf_remove_uwtmp();
  407. }
  408. static int
  409. pam_conv_func(int nmsg, const struct pam_message** p_msg,
  410.               struct pam_response** p_reply, void* p_addata)
  411. {
  412.   int i;
  413.   struct pam_response* p_resps = 0;
  414.   (void) p_addata;
  415.   if (nmsg < 0)
  416.   {
  417.     bug("dodgy nmsg in pam_conv_func");
  418.   }
  419.   p_resps = vsf_sysutil_malloc(sizeof(struct pam_response) * nmsg);
  420.   for (i=0; i<nmsg; i++)
  421.   {
  422.     switch (p_msg[i]->msg_style)
  423.     {
  424.       case PAM_PROMPT_ECHO_OFF:
  425.         p_resps[i].resp_retcode = PAM_SUCCESS;
  426.         p_resps[i].resp = (char*) str_strdup(&s_pword_str);
  427.         break;
  428.       case PAM_TEXT_INFO:
  429.       case PAM_ERROR_MSG:
  430.         p_resps[i].resp_retcode = PAM_SUCCESS;
  431.         p_resps[i].resp = 0;
  432.         break;
  433.       case PAM_PROMPT_ECHO_ON:
  434.       default:
  435.         vsf_sysutil_free(p_resps);
  436.         return PAM_CONV_ERR;
  437.         break;
  438.     }
  439.   }
  440.   *p_reply = p_resps;
  441.   return PAM_SUCCESS;
  442. }
  443. #endif /* VSF_SYSDEP_HAVE_PAM */
  444. /* Capabilities support (or lack thereof) */
  445. void
  446. vsf_sysdep_keep_capabilities(void)
  447. {
  448.   if (!vsf_sysdep_has_capabilities_as_non_root())
  449.   {
  450.     bug("asked to keep capabilities, but no support exists");
  451.   }
  452. #ifdef VSF_SYSDEP_HAVE_SETKEEPCAPS
  453.   {
  454.     int retval = prctl(PR_SET_KEEPCAPS, 1);
  455.     if (vsf_sysutil_retval_is_error(retval))
  456.     {
  457.       die("prctl");
  458.     }
  459.   }
  460. #endif /* VSF_SYSDEP_HAVE_SETKEEPCAPS */
  461. }
  462. #if !defined(VSF_SYSDEP_HAVE_CAPABILITIES) && !defined(VSF_SYSDEP_HAVE_LIBCAP)
  463. int
  464. vsf_sysdep_has_capabilities(void)
  465. {
  466.   return 0;
  467. }
  468. int
  469. vsf_sysdep_has_capabilities_as_non_root(void)
  470. {
  471.   return 0;
  472. }
  473. void
  474. vsf_sysdep_adopt_capabilities(unsigned int caps)
  475. {
  476.   (void) caps;
  477.   bug("asked to adopt capabilities, but no support exists");
  478. }
  479. #else /* VSF_SYSDEP_HAVE_CAPABILITIES || VSF_SYSDEP_HAVE_LIBCAP */
  480. static int do_checkcap(void);
  481. int
  482. vsf_sysdep_has_capabilities_as_non_root(void)
  483. {
  484.   static int s_prctl_checked;
  485.   static int s_runtime_prctl_works;
  486.   if (!s_prctl_checked)
  487.   {
  488.   #ifdef VSF_SYSDEP_HAVE_SETKEEPCAPS
  489.     /* Clarity: note embedded call to prctl() syscall */
  490.     if (!vsf_sysutil_retval_is_error(prctl(PR_SET_KEEPCAPS, 0)))
  491.     {
  492.       s_runtime_prctl_works = 1;
  493.     }
  494.   #endif /* VSF_SYSDEP_HAVE_SETKEEPCAPS */
  495.     s_prctl_checked = 1;
  496.   }
  497.   return s_runtime_prctl_works;
  498. }
  499. int
  500. vsf_sysdep_has_capabilities(void)
  501. {
  502.   /* Even though compiled with capabilities, the runtime system may lack them.
  503.    * Also, RH7.0 kernel headers advertise a 2.4.0 box, but on a 2.2.x kernel!
  504.    */
  505.   static int s_caps_checked;
  506.   static int s_runtime_has_caps;
  507.   if (!s_caps_checked)
  508.   {
  509.     s_runtime_has_caps = do_checkcap();
  510.     s_caps_checked = 1;
  511.   }
  512.   return s_runtime_has_caps;
  513. }
  514.   
  515.   #ifndef VSF_SYSDEP_HAVE_LIBCAP
  516. static int
  517. do_checkcap(void)
  518. {
  519.   /* EFAULT (EINVAL if page 0 mapped) vs. ENOSYS */
  520.   int retval = capset(0, 0);
  521.   if (!vsf_sysutil_retval_is_error(retval) ||
  522.       vsf_sysutil_get_error() != kVSFSysUtilErrNOSYS)
  523.   {
  524.     return 1;
  525.   }
  526.   return 0;
  527. }
  528. void
  529. vsf_sysdep_adopt_capabilities(unsigned int caps)
  530. {
  531.   /* n.b. yes I know I should be using libcap!! */
  532.   int retval;
  533.   struct __user_cap_header_struct cap_head;
  534.   struct __user_cap_data_struct cap_data;
  535.   __u32 cap_mask = 0;
  536.   if (!caps)
  537.   {
  538.     bug("asked to adopt no capabilities");
  539.   }
  540.   vsf_sysutil_memclr(&cap_head, sizeof(cap_head));
  541.   vsf_sysutil_memclr(&cap_data, sizeof(cap_data));
  542.   cap_head.version = _LINUX_CAPABILITY_VERSION;
  543.   cap_head.pid = 0;
  544.   if (caps & kCapabilityCAP_CHOWN)
  545.   {
  546.     cap_mask |= (1 << CAP_CHOWN);
  547.   }
  548.   if (caps & kCapabilityCAP_NET_BIND_SERVICE)
  549.   {
  550.     cap_mask |= (1 << CAP_NET_BIND_SERVICE);
  551.   }
  552.   cap_data.effective = cap_data.permitted = cap_mask;
  553.   cap_data.inheritable = 0;
  554.   retval = capset(&cap_head, &cap_data);
  555.   if (retval != 0)
  556.   {
  557.     die("capset");
  558.   }
  559. }
  560.   #else /* VSF_SYSDEP_HAVE_LIBCAP */
  561. static int
  562. do_checkcap(void)
  563. {
  564.   cap_t current_caps = cap_get_proc();
  565.   cap_free(current_caps);
  566.   if (current_caps != NULL)
  567.   {
  568.     return 1;
  569.   }
  570.   return 0;
  571. }
  572. void
  573. vsf_sysdep_adopt_capabilities(unsigned int caps)
  574. {
  575.   int retval;
  576.   cap_value_t cap_value;
  577.   cap_t adopt_caps = cap_init();
  578.   if (caps & kCapabilityCAP_CHOWN)
  579.   {
  580.     cap_value = CAP_CHOWN;
  581.     cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);
  582.     cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);
  583.   }
  584.   if (caps & kCapabilityCAP_NET_BIND_SERVICE)
  585.   {
  586.     cap_value = CAP_NET_BIND_SERVICE;
  587.     cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);
  588.     cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);
  589.   }
  590.   retval = cap_set_proc(adopt_caps);
  591.   if (retval != 0)
  592.   {
  593.     die("cap_set_proc");
  594.   }
  595.   cap_free(adopt_caps);
  596. }
  597.   #endif /* !VSF_SYSDEP_HAVE_LIBCAP */
  598. #endif /* VSF_SYSDEP_HAVE_CAPABILITIES || VSF_SYSDEP_HAVE_LIBCAP */
  599. int
  600. vsf_sysutil_sendfile(const int out_fd, const int in_fd,
  601.                      filesize_t* p_offset, filesize_t num_send,
  602.                      unsigned int max_chunk)
  603. {
  604.   /* Grr - why is off_t signed? */
  605.   if (*p_offset < 0 || num_send < 0)
  606.   {
  607.     die("invalid offset or send count in vsf_sysutil_sendfile");
  608.   }
  609.   if (max_chunk == 0)
  610.   {
  611.     max_chunk = INT_MAX;
  612.   }
  613.   while (num_send > 0)
  614.   {
  615.     int retval;
  616.     unsigned int send_this_time;
  617.     if (num_send > max_chunk)
  618.     {
  619.       send_this_time = max_chunk;
  620.     }
  621.     else
  622.     {
  623.       send_this_time = (unsigned int) num_send;
  624.     }
  625.     /* Keep input file position in line with sendfile() calls */
  626.     vsf_sysutil_lseek_to(in_fd, *p_offset);
  627.     retval = do_sendfile(out_fd, in_fd, send_this_time, *p_offset);
  628.     if (vsf_sysutil_retval_is_error(retval) || retval == 0)
  629.     {
  630.       return retval;
  631.     }
  632.     num_send -= retval;
  633.     *p_offset += retval;
  634.   }
  635.   return 0;
  636. }
  637. static int do_sendfile(const int out_fd, const int in_fd,
  638.                        unsigned int num_send, filesize_t start_pos)
  639. {
  640.   /* Probably should one day be shared with instance in ftpdataio.c */
  641.   static char* p_recvbuf;
  642.   unsigned int total_written = 0;
  643.   int retval;
  644.   enum EVSFSysUtilError error;
  645.   (void) start_pos;
  646.   (void) error;
  647. #if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || 
  648.     defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) || 
  649.     defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE) || 
  650.     defined(VSF_SYSDEP_HAVE_AIX_SENDFILE) || 
  651.     defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  652.   if (tunable_use_sendfile)
  653.   {
  654.     static int s_sendfile_checked;
  655.     static int s_runtime_sendfile_works;
  656.     if (!s_sendfile_checked || s_runtime_sendfile_works)
  657.     {
  658.       do
  659.       {
  660.   #ifdef VSF_SYSDEP_HAVE_LINUX_SENDFILE
  661.         retval = sendfile(out_fd, in_fd, NULL, num_send);
  662.   #elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE)
  663.         {
  664.           /* XXX - start_pos will truncate on 32-bit machines - can we
  665.            * say "start from current pos"?
  666.            */
  667.           off_t written = 0;
  668.           retval = sendfile(in_fd, out_fd, start_pos, num_send, NULL,
  669.                             &written, 0);
  670.           /* Translate to Linux-like retval */
  671.           if (written > 0)
  672.           {
  673.             retval = (int) written;
  674.           }
  675.         }
  676.   #elif defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  677.         {
  678.           size_t written = 0;
  679.           struct sendfilevec the_vec;
  680.           vsf_sysutil_memclr(&the_vec, sizeof(the_vec));
  681.           the_vec.sfv_fd = in_fd;
  682.           the_vec.sfv_off = start_pos;
  683.           the_vec.sfv_len = num_send;
  684.           retval = sendfilev(out_fd, &the_vec, 1, &written);
  685.           /* Translate to Linux-like retval */
  686.           if (written > 0)
  687.           {
  688.             retval = (int) written;
  689.           }
  690.         }
  691.   #elif defined(VSF_SYSDEP_HAVE_AIX_SENDFILE)
  692.         {
  693.           struct sf_parms sf_iobuf;
  694.           vsf_sysutil_memclr(&sf_iobuf, sizeof(sf_iobuf));
  695.           sf_iobuf.header_data = NULL;
  696.           sf_iobuf.header_length = 0;
  697.           sf_iobuf.trailer_data = NULL;
  698.           sf_iobuf.trailer_length = 0;
  699.           sf_iobuf.file_descriptor = in_fd;
  700.           sf_iobuf.file_offset = start_pos;
  701.           sf_iobuf.file_bytes = num_send;
  702.           retval = send_file((int*)&out_fd, &sf_iobuf, 0);
  703.           if (retval >= 0)
  704.           {
  705.             retval = sf_iobuf.bytes_sent;
  706.           }
  707.         }
  708.   #else /* must be VSF_SYSDEP_HAVE_HPUX_SENDFILE */
  709.         {
  710.           retval = sendfile(out_fd, in_fd, start_pos, num_send, NULL, 0);
  711.         }
  712.   #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */
  713.         error = vsf_sysutil_get_error();
  714.         vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, out_fd);
  715.       }
  716.       while (vsf_sysutil_retval_is_error(retval) &&
  717.              error == kVSFSysUtilErrINTR);
  718.       if (!s_sendfile_checked)
  719.       {
  720.         s_sendfile_checked = 1;
  721.         if (!vsf_sysutil_retval_is_error(retval) ||
  722.             error != kVSFSysUtilErrNOSYS)
  723.         {
  724.           s_runtime_sendfile_works = 1;
  725.         }
  726.       }
  727.       if (!vsf_sysutil_retval_is_error(retval))
  728.       {
  729.         return retval;
  730.       }
  731.       if (s_runtime_sendfile_works && error != kVSFSysUtilErrINVAL &&
  732.           error != kVSFSysUtilErrOPNOTSUPP)
  733.       {
  734.         return retval;
  735.       }
  736.       /* Fall thru to normal implementation. We won't check again. NOTE -
  737.        * also falls through if sendfile() is OK but it returns EINVAL. For
  738.        * Linux this means the file was not page cache backed. Original
  739.        * complaint was trying to serve files from an NTFS filesystem!
  740.        */
  741.     }
  742.   }
  743. #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE || VSF_SYSDEP_HAVE_FREEBSD_SENDFILE */
  744.   if (p_recvbuf == 0)
  745.   {
  746.     vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE);
  747.   }
  748.   while (1)
  749.   {
  750.     unsigned int num_read;
  751.     unsigned int num_written;
  752.     unsigned int num_read_this_time = VSFTP_DATA_BUFSIZE;
  753.     if (num_read_this_time > num_send)
  754.     {
  755.       num_read_this_time = num_send;
  756.     }
  757.     retval = vsf_sysutil_read(in_fd, p_recvbuf, num_read_this_time);
  758.     if (retval < 0)
  759.     {
  760.       return retval;
  761.     }
  762.     else if (retval == 0)
  763.     {
  764.       return -1;
  765.     }
  766.     num_read = (unsigned int) retval;
  767.     retval = vsf_sysutil_write_loop(out_fd, p_recvbuf, num_read);
  768.     if (retval < 0)
  769.     {
  770.       return retval;
  771.     }
  772.     num_written = (unsigned int) retval;
  773.     total_written += num_written;
  774.     if (num_written != num_read)
  775.     {
  776.       return num_written;
  777.     }
  778.     if (num_written > num_send)
  779.     {
  780.       bug("num_written bigger than num_send in do_sendfile");
  781.     }
  782.     num_send -= num_written;
  783.     if (num_send == 0)
  784.     {
  785.       /* Bingo! */
  786.       return total_written;
  787.     }
  788.   }
  789. }
  790. void
  791. vsf_sysutil_set_proctitle_prefix(const struct mystr* p_str)
  792. {
  793.   str_copy(&s_proctitle_prefix_str, p_str);
  794. }
  795. /* This delegation is common to all setproctitle() implementations */
  796. void
  797. vsf_sysutil_setproctitle_str(const struct mystr* p_str)
  798. {
  799.   vsf_sysutil_setproctitle(str_getbuf(p_str));
  800. }
  801. void
  802. vsf_sysutil_setproctitle(const char* p_text)
  803. {
  804.   struct mystr proctitle_str = INIT_MYSTR;
  805.   str_copy(&proctitle_str, &s_proctitle_prefix_str);
  806.   if (!str_isempty(&proctitle_str))
  807.   {
  808.     str_append_text(&proctitle_str, ": ");
  809.   }
  810.   str_append_text(&proctitle_str, p_text);
  811.   vsf_sysutil_setproctitle_internal(str_getbuf(&proctitle_str));
  812.   str_free(&proctitle_str);
  813. }
  814. #ifdef VSF_SYSDEP_HAVE_SETPROCTITLE
  815. void
  816. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  817. {
  818.   (void) argc;
  819.   (void) argv;
  820. }
  821. void
  822. vsf_sysutil_setproctitle_internal(const char* p_buf)
  823. {
  824.   setproctitle("%s", p_buf);
  825. }
  826. #elif defined(VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE)
  827. void
  828. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  829. {
  830.   (void) argc;
  831.   (void) argv;
  832. }
  833. void
  834. vsf_sysutil_setproctitle_internal(const char* p_buf)
  835. {
  836.   struct mystr proctitle_str = INIT_MYSTR;
  837.   union pstun p;
  838.   str_alloc_text(&proctitle_str, "vsftpd: ");
  839.   str_append_text(&proctitle_str, p_buf);
  840.   p.pst_command = str_getbuf(&proctitle_str);
  841.   pstat(PSTAT_SETCMD, p, 0, 0, 0);
  842.   str_free(&proctitle_str);
  843. }
  844. #elif defined(VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK)
  845. void
  846. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  847. {
  848.   int i;
  849.   char** p_env = environ;
  850.   if (s_proctitle_inited)
  851.   {
  852.     bug("vsf_sysutil_setproctitle_init called twice");
  853.   }
  854.   s_proctitle_inited = 1;
  855.   if (argv[0] == 0)
  856.   {
  857.     die("no argv[0] in vsf_sysutil_setproctitle_init");
  858.   }
  859.   for (i=0; i<argc; i++)
  860.   {
  861.     s_proctitle_space += vsf_sysutil_strlen(argv[i]) + 1;
  862.     if (i > 0)
  863.     {
  864.       argv[i] = 0;
  865.     }
  866.   }
  867.   while (*p_env != 0)
  868.   {
  869.     s_proctitle_space += vsf_sysutil_strlen(*p_env) + 1;
  870.     p_env++;
  871.   }
  872.   /* Oops :-) */
  873.   environ = 0;
  874.   s_p_proctitle = (char*) argv[0];
  875.   vsf_sysutil_memclr(s_p_proctitle, s_proctitle_space);
  876. }
  877. void
  878. vsf_sysutil_setproctitle_internal(const char* p_buf)
  879. {
  880.   struct mystr proctitle_str = INIT_MYSTR;
  881.   unsigned int to_copy;
  882.   if (!s_proctitle_inited)
  883.   {
  884.     bug("vsf_sysutil_setproctitle: not initialized");
  885.   }
  886.   vsf_sysutil_memclr(s_p_proctitle, s_proctitle_space);
  887.   if (s_proctitle_space < 32)
  888.   {
  889.     return;
  890.   }
  891.   str_alloc_text(&proctitle_str, "vsftpd: ");
  892.   str_append_text(&proctitle_str, p_buf);
  893.   to_copy = str_getlen(&proctitle_str);
  894.   if (to_copy > s_proctitle_space - 1)
  895.   {
  896.     to_copy = s_proctitle_space - 1;
  897.   }
  898.   vsf_sysutil_memcpy(s_p_proctitle, str_getbuf(&proctitle_str), to_copy);
  899.   str_free(&proctitle_str);
  900.   s_p_proctitle[to_copy] = '';
  901. }
  902. #else /* VSF_SYSDEP_HAVE_SETPROCTITLE */
  903. void
  904. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  905. {
  906.   (void) argc;
  907.   (void) argv;
  908. }
  909. void
  910. vsf_sysutil_setproctitle_internal(const char* p_buf)
  911. {
  912.   (void) p_buf;
  913. }
  914. #endif /* VSF_SYSDEP_HAVE_SETPROCTITLE */
  915. #ifdef VSF_SYSDEP_HAVE_MAP_ANON
  916. void
  917. vsf_sysutil_map_anon_pages_init(void)
  918. {
  919. }
  920. void*
  921. vsf_sysutil_map_anon_pages(unsigned int length)
  922. {
  923.   char* retval = mmap(0, length, PROT_READ | PROT_WRITE,
  924.                       MAP_PRIVATE | MAP_ANON, -1, 0);
  925.   if (retval == MAP_FAILED)
  926.   {
  927.     die("mmap");
  928.   }
  929.   return retval;
  930. }
  931. #else /* VSF_SYSDEP_HAVE_MAP_ANON */
  932. void
  933. vsf_sysutil_map_anon_pages_init(void)
  934. {
  935.   if (s_zero_fd != -1)
  936.   {
  937.     bug("vsf_sysutil_map_anon_pages_init called twice");
  938.   }
  939.   s_zero_fd = open("/dev/zero", O_RDWR);
  940.   if (s_zero_fd < 0)
  941.   {
  942.     die("could not open /dev/zero");
  943.   }
  944. }
  945. void*
  946. vsf_sysutil_map_anon_pages(unsigned int length)
  947. {
  948.   char* retval = mmap(0, length, PROT_READ | PROT_WRITE,
  949.                       MAP_PRIVATE, s_zero_fd, 0);
  950.   if (retval == MAP_FAILED)
  951.   {
  952.     die("mmap");
  953.   }
  954.   return retval;
  955. }
  956. #endif /* VSF_SYSDEP_HAVE_MAP_ANON */
  957. #ifndef VSF_SYSDEP_NEED_OLD_FD_PASSING
  958. void
  959. vsf_sysutil_send_fd(int sock_fd, int send_fd)
  960. {
  961.   int retval;
  962.   struct msghdr msg;
  963.   struct cmsghdr* p_cmsg;
  964.   struct iovec vec;
  965.   char cmsgbuf[CMSG_SPACE(sizeof(send_fd))];
  966.   int* p_fds;
  967.   char sendchar = 0;
  968.   msg.msg_control = cmsgbuf;
  969.   msg.msg_controllen = sizeof(cmsgbuf);
  970.   p_cmsg = CMSG_FIRSTHDR(&msg);
  971.   p_cmsg->cmsg_level = SOL_SOCKET;
  972.   p_cmsg->cmsg_type = SCM_RIGHTS;
  973.   p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
  974.   p_fds = (int*)CMSG_DATA(p_cmsg);
  975.   *p_fds = send_fd;
  976.   msg.msg_controllen = p_cmsg->cmsg_len;
  977.   msg.msg_name = NULL;
  978.   msg.msg_namelen = 0;
  979.   msg.msg_iov = &vec;
  980.   msg.msg_iovlen = 1;
  981.   msg.msg_flags = 0;
  982.   /* "To pass file descriptors or credentials you need to send/read at
  983.    * least on byte" (man 7 unix)
  984.    */
  985.   vec.iov_base = &sendchar;
  986.   vec.iov_len = sizeof(sendchar);
  987.   retval = sendmsg(sock_fd, &msg, 0);
  988.   if (retval != 1)
  989.   {
  990.     die("sendmsg");
  991.   }
  992. }
  993. int
  994. vsf_sysutil_recv_fd(const int sock_fd)
  995. {
  996.   int retval;
  997.   struct msghdr msg;
  998.   char recvchar;
  999.   struct iovec vec;
  1000.   int recv_fd;
  1001.   char cmsgbuf[CMSG_SPACE(sizeof(recv_fd))];
  1002.   struct cmsghdr* p_cmsg;
  1003.   int* p_fd;
  1004.   vec.iov_base = &recvchar;
  1005.   vec.iov_len = sizeof(recvchar);
  1006.   msg.msg_name = NULL;
  1007.   msg.msg_namelen = 0;
  1008.   msg.msg_iov = &vec;
  1009.   msg.msg_iovlen = 1;
  1010.   msg.msg_control = cmsgbuf;
  1011.   msg.msg_controllen = sizeof(cmsgbuf);
  1012.   msg.msg_flags = 0;
  1013.   /* In case something goes wrong, set the fd to -1 before the syscall */
  1014.   p_fd = (int*)CMSG_DATA(CMSG_FIRSTHDR(&msg));
  1015.   *p_fd = -1;  
  1016.   retval = recvmsg(sock_fd, &msg, 0);
  1017.   if (retval != 1)
  1018.   {
  1019.     die("recvmsg");
  1020.   }
  1021.   p_cmsg = CMSG_FIRSTHDR(&msg);
  1022.   if (p_cmsg == NULL)
  1023.   {
  1024.     die("no passed fd");
  1025.   }
  1026.   /* We used to verify the returned cmsg_level, cmsg_type and cmsg_len here,
  1027.    * but Linux 2.0 totally uselessly fails to fill these in.
  1028.    */
  1029.   p_fd = (int*)CMSG_DATA(p_cmsg);
  1030.   recv_fd = *p_fd;
  1031.   if (recv_fd == -1)
  1032.   {
  1033.     die("no passed fd");
  1034.   }
  1035.   return recv_fd;
  1036. }
  1037. #else /* !VSF_SYSDEP_NEED_OLD_FD_PASSING */
  1038. void
  1039. vsf_sysutil_send_fd(int sock_fd, int send_fd)
  1040. {
  1041.   int retval;
  1042.   char send_char = 0;
  1043.   struct msghdr msg;
  1044.   struct iovec vec;
  1045.   vec.iov_base = &send_char;
  1046.   vec.iov_len = 1;
  1047.   msg.msg_name = NULL;
  1048.   msg.msg_namelen = 0;
  1049.   msg.msg_iov = &vec;
  1050.   msg.msg_iovlen = 1;
  1051.   msg.msg_accrights = (caddr_t) &send_fd;
  1052.   msg.msg_accrightslen = sizeof(send_fd);
  1053.   retval = sendmsg(sock_fd, &msg, 0);
  1054.   if (retval != 1)
  1055.   {
  1056.     die("sendmsg");
  1057.   }
  1058. }
  1059. int
  1060. vsf_sysutil_recv_fd(int sock_fd)
  1061. {
  1062.   int retval;
  1063.   struct msghdr msg;
  1064.   struct iovec vec;
  1065.   char recv_char;
  1066.   int recv_fd = -1;
  1067.   vec.iov_base = &recv_char;
  1068.   vec.iov_len = 1;
  1069.   msg.msg_name = NULL;
  1070.   msg.msg_namelen = 0;
  1071.   msg.msg_iov = &vec;
  1072.   msg.msg_iovlen = 1;
  1073.   msg.msg_accrights = (caddr_t) &recv_fd;
  1074.   msg.msg_accrightslen = sizeof(recv_fd);
  1075.   retval = recvmsg(sock_fd, &msg, 0);
  1076.   if (retval != 1)
  1077.   {
  1078.     die("recvmsg");
  1079.   }
  1080.   if (recv_fd == -1)
  1081.   {
  1082.     die("no passed fd");
  1083.   }
  1084.   return recv_fd;
  1085. }
  1086. #endif /* !VSF_SYSDEP_NEED_OLD_FD_PASSING */
  1087. #ifndef VSF_SYSDEP_HAVE_UTMPX
  1088. void
  1089. vsf_insert_uwtmp(const struct mystr* p_user_str,
  1090.                  const struct mystr* p_host_str)
  1091. {
  1092.   (void) p_user_str;
  1093.   (void) p_host_str;
  1094. }
  1095. void
  1096. vsf_remove_uwtmp(void)
  1097. {
  1098. }
  1099. #else /* !VSF_SYSDEP_HAVE_UTMPX */
  1100. /* IMHO, the pam_unix module REALLY should be doing this in its SM component */
  1101. /* Statics */
  1102. static int s_uwtmp_inserted;
  1103. static struct utmpx s_utent;
  1104. void
  1105. vsf_insert_uwtmp(const struct mystr* p_user_str,
  1106.                  const struct mystr* p_host_str)
  1107. {
  1108.   if (sizeof(s_utent.ut_line) < 16)
  1109.   {
  1110.     return;
  1111.   }
  1112.   if (s_uwtmp_inserted)
  1113.   {
  1114.     bug("vsf_insert_uwtmp");
  1115.   }
  1116.   {
  1117.     struct mystr line_str = INIT_MYSTR;
  1118.     str_alloc_text(&line_str, "vsftpd:");
  1119.     str_append_ulong(&line_str, vsf_sysutil_getpid());
  1120.     if (str_getlen(&line_str) >= sizeof(s_utent.ut_line))
  1121.     {
  1122.       str_free(&line_str);
  1123.       return;
  1124.     }
  1125.     vsf_sysutil_strcpy(s_utent.ut_line, str_getbuf(&line_str),
  1126.                        sizeof(s_utent.ut_line));
  1127.     str_free(&line_str);
  1128.   }
  1129.   s_uwtmp_inserted = 1;
  1130.   s_utent.ut_type = USER_PROCESS;
  1131.   s_utent.ut_pid = vsf_sysutil_getpid();
  1132.   vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str),
  1133.                      sizeof(s_utent.ut_user));
  1134.   vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str),
  1135.                      sizeof(s_utent.ut_host));
  1136.   s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec();
  1137.   setutxent();
  1138.   (void) pututxline(&s_utent);
  1139.   endutxent();
  1140.   updwtmpx(WTMPX_FILE, &s_utent);
  1141. }
  1142. void
  1143. vsf_remove_uwtmp(void)
  1144. {
  1145.   if (!s_uwtmp_inserted)
  1146.   {
  1147.     return;
  1148.   }
  1149.   s_uwtmp_inserted = 0;
  1150.   s_utent.ut_type = DEAD_PROCESS;
  1151.   vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user));
  1152.   vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host));
  1153.   s_utent.ut_tv.tv_sec = 0;
  1154.   setutxent();
  1155.   (void) pututxline(&s_utent);
  1156.   endutxent();
  1157.   s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec();
  1158.   updwtmpx(WTMPX_FILE, &s_utent);
  1159. }
  1160. #endif /* !VSF_SYSDEP_HAVE_UTMPX */
  1161. void
  1162. vsf_set_die_if_parent_dies()
  1163. {
  1164. #ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG
  1165.   if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) != 0)
  1166.   {
  1167.     die("prctl");
  1168.   }
  1169. #endif
  1170. }
  1171. void
  1172. vsf_set_term_if_parent_dies()
  1173. {
  1174. #ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG
  1175.   if (prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) != 0)
  1176.   {
  1177.     die("prctl");
  1178.   }
  1179. #endif
  1180. }
  1181. int
  1182. vsf_sysutil_fork_isolate_failok()
  1183. {
  1184. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1185.   static int cloneflags_work = 1;
  1186.   if (cloneflags_work)
  1187.   {
  1188.     int ret = syscall(__NR_clone, CLONE_NEWPID | CLONE_NEWIPC | SIGCHLD, NULL);
  1189.     if (ret != -1 || (errno != EINVAL && errno != EPERM))
  1190.     {
  1191.       if (ret == 0)
  1192.       {
  1193.         vsf_sysutil_post_fork();
  1194.       }
  1195.       return ret;
  1196.     }
  1197.     cloneflags_work = 0;
  1198.   }
  1199. #endif
  1200.   return vsf_sysutil_fork_failok();
  1201. }
  1202. int
  1203. vsf_sysutil_fork_newnet()
  1204. {
  1205. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1206.   static int cloneflags_work = 1;
  1207.   if (cloneflags_work)
  1208.   {
  1209.     int ret = syscall(__NR_clone, CLONE_NEWNET | SIGCHLD, NULL);
  1210.     if (ret != -1 || (errno != EINVAL && errno != EPERM))
  1211.     {
  1212.       if (ret == 0)
  1213.       {
  1214.         vsf_sysutil_post_fork();
  1215.       }
  1216.       return ret;
  1217.     }
  1218.     cloneflags_work = 0;
  1219.   }
  1220. #endif
  1221.   return vsf_sysutil_fork();
  1222. }
  1223. int
  1224. vsf_sysutil_getpid_nocache(void)
  1225. {
  1226. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1227.   /* Need to defeat the glibc pid caching because we need to hit a raw
  1228.    * sys_clone() above.
  1229.    */
  1230.   return syscall(__NR_getpid);
  1231. #else
  1232.   return getpid();
  1233. #endif
  1234. }