sysdeputil.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  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 = -1;
  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. if (tunable_pam_service_name)
  305. {
  306. retval = pam_start(tunable_pam_service_name,
  307. str_getbuf(p_user_str), &the_conv, &s_pamh);
  308. }
  309. if (retval != PAM_SUCCESS)
  310. {
  311. s_pamh = 0;
  312. return 0;
  313. }
  314. #ifdef PAM_RHOST
  315. retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host));
  316. if (retval != PAM_SUCCESS)
  317. {
  318. (void) pam_end(s_pamh, retval);
  319. s_pamh = 0;
  320. return 0;
  321. }
  322. #endif
  323. #ifdef PAM_TTY
  324. retval = pam_set_item(s_pamh, PAM_TTY, "ftp");
  325. if (retval != PAM_SUCCESS)
  326. {
  327. (void) pam_end(s_pamh, retval);
  328. s_pamh = 0;
  329. return 0;
  330. }
  331. #endif
  332. #ifdef PAM_RUSER
  333. retval = pam_set_item(s_pamh, PAM_RUSER, str_getbuf(p_user_str));
  334. if (retval != PAM_SUCCESS)
  335. {
  336. (void) pam_end(s_pamh, retval);
  337. s_pamh = 0;
  338. return 0;
  339. }
  340. #endif
  341. retval = pam_authenticate(s_pamh, 0);
  342. if (retval != PAM_SUCCESS)
  343. {
  344. (void) pam_end(s_pamh, retval);
  345. s_pamh = 0;
  346. return 0;
  347. }
  348. #ifdef PAM_USER
  349. retval = pam_get_item(s_pamh, PAM_USER, &item);
  350. if (retval != PAM_SUCCESS)
  351. {
  352. (void) pam_end(s_pamh, retval);
  353. s_pamh = 0;
  354. return 0;
  355. }
  356. pam_user_name = item;
  357. str_alloc_text(p_user_str, pam_user_name);
  358. #endif
  359. retval = pam_acct_mgmt(s_pamh, 0);
  360. if (retval != PAM_SUCCESS)
  361. {
  362. (void) pam_end(s_pamh, retval);
  363. s_pamh = 0;
  364. return 0;
  365. }
  366. retval = pam_setcred(s_pamh, PAM_ESTABLISH_CRED);
  367. if (retval != PAM_SUCCESS)
  368. {
  369. (void) pam_end(s_pamh, retval);
  370. s_pamh = 0;
  371. return 0;
  372. }
  373. if (!tunable_session_support)
  374. {
  375. /* You're in already! */
  376. (void) pam_end(s_pamh, retval);
  377. s_pamh = 0;
  378. return 1;
  379. }
  380. /* Must do this BEFORE opening a session for pam_limits to count us */
  381. vsf_insert_uwtmp(p_user_str, p_remote_host);
  382. retval = pam_open_session(s_pamh, 0);
  383. if (retval != PAM_SUCCESS)
  384. {
  385. vsf_remove_uwtmp();
  386. (void) pam_setcred(s_pamh, PAM_DELETE_CRED);
  387. (void) pam_end(s_pamh, retval);
  388. s_pamh = 0;
  389. return 0;
  390. }
  391. /* We MUST ensure the PAM session, utmp, wtmp etc. are cleaned up, however
  392. * we exit.
  393. */
  394. vsf_sysutil_set_exit_func(vsf_auth_shutdown);
  395. /* You're in dude */
  396. return 1;
  397. }
  398. static void
  399. vsf_auth_shutdown(void)
  400. {
  401. if (s_pamh == 0)
  402. {
  403. bug("auth_shutdown");
  404. }
  405. (void) pam_close_session(s_pamh, 0);
  406. (void) pam_setcred(s_pamh, PAM_DELETE_CRED);
  407. (void) pam_end(s_pamh, PAM_SUCCESS);
  408. s_pamh = 0;
  409. vsf_remove_uwtmp();
  410. }
  411. static int
  412. pam_conv_func(int nmsg, const struct pam_message** p_msg,
  413. struct pam_response** p_reply, void* p_addata)
  414. {
  415. int i;
  416. struct pam_response* p_resps = 0;
  417. (void) p_addata;
  418. if (nmsg < 0)
  419. {
  420. bug("dodgy nmsg in pam_conv_func");
  421. }
  422. p_resps = vsf_sysutil_malloc(sizeof(struct pam_response) * nmsg);
  423. for (i=0; i<nmsg; i++)
  424. {
  425. switch (p_msg[i]->msg_style)
  426. {
  427. case PAM_PROMPT_ECHO_OFF:
  428. p_resps[i].resp_retcode = PAM_SUCCESS;
  429. p_resps[i].resp = (char*) str_strdup(&s_pword_str);
  430. break;
  431. case PAM_TEXT_INFO:
  432. case PAM_ERROR_MSG:
  433. p_resps[i].resp_retcode = PAM_SUCCESS;
  434. p_resps[i].resp = 0;
  435. break;
  436. case PAM_PROMPT_ECHO_ON:
  437. default:
  438. vsf_sysutil_free(p_resps);
  439. return PAM_CONV_ERR;
  440. break;
  441. }
  442. }
  443. *p_reply = p_resps;
  444. return PAM_SUCCESS;
  445. }
  446. #endif /* VSF_SYSDEP_HAVE_PAM */
  447. /* Capabilities support (or lack thereof) */
  448. void
  449. vsf_sysdep_keep_capabilities(void)
  450. {
  451. if (!vsf_sysdep_has_capabilities_as_non_root())
  452. {
  453. bug("asked to keep capabilities, but no support exists");
  454. }
  455. #ifdef VSF_SYSDEP_HAVE_SETKEEPCAPS
  456. {
  457. int retval = prctl(PR_SET_KEEPCAPS, 1);
  458. if (vsf_sysutil_retval_is_error(retval))
  459. {
  460. die("prctl");
  461. }
  462. }
  463. #endif /* VSF_SYSDEP_HAVE_SETKEEPCAPS */
  464. }
  465. #if !defined(VSF_SYSDEP_HAVE_CAPABILITIES) && !defined(VSF_SYSDEP_HAVE_LIBCAP)
  466. int
  467. vsf_sysdep_has_capabilities(void)
  468. {
  469. return 0;
  470. }
  471. int
  472. vsf_sysdep_has_capabilities_as_non_root(void)
  473. {
  474. return 0;
  475. }
  476. void
  477. vsf_sysdep_adopt_capabilities(unsigned int caps)
  478. {
  479. (void) caps;
  480. bug("asked to adopt capabilities, but no support exists");
  481. }
  482. #else /* VSF_SYSDEP_HAVE_CAPABILITIES || VSF_SYSDEP_HAVE_LIBCAP */
  483. static int do_checkcap(void);
  484. int
  485. vsf_sysdep_has_capabilities_as_non_root(void)
  486. {
  487. static int s_prctl_checked;
  488. static int s_runtime_prctl_works;
  489. if (!s_prctl_checked)
  490. {
  491. #ifdef VSF_SYSDEP_HAVE_SETKEEPCAPS
  492. /* Clarity: note embedded call to prctl() syscall */
  493. if (!vsf_sysutil_retval_is_error(prctl(PR_SET_KEEPCAPS, 0)))
  494. {
  495. s_runtime_prctl_works = 1;
  496. }
  497. #endif /* VSF_SYSDEP_HAVE_SETKEEPCAPS */
  498. s_prctl_checked = 1;
  499. }
  500. return s_runtime_prctl_works;
  501. }
  502. int
  503. vsf_sysdep_has_capabilities(void)
  504. {
  505. /* Even though compiled with capabilities, the runtime system may lack them.
  506. * Also, RH7.0 kernel headers advertise a 2.4.0 box, but on a 2.2.x kernel!
  507. */
  508. static int s_caps_checked;
  509. static int s_runtime_has_caps;
  510. if (!s_caps_checked)
  511. {
  512. s_runtime_has_caps = do_checkcap();
  513. s_caps_checked = 1;
  514. }
  515. return s_runtime_has_caps;
  516. }
  517. #ifndef VSF_SYSDEP_HAVE_LIBCAP
  518. static int
  519. do_checkcap(void)
  520. {
  521. /* EFAULT (EINVAL if page 0 mapped) vs. ENOSYS */
  522. int retval = capset(0, 0);
  523. if (!vsf_sysutil_retval_is_error(retval) ||
  524. vsf_sysutil_get_error() != kVSFSysUtilErrNOSYS)
  525. {
  526. return 1;
  527. }
  528. return 0;
  529. }
  530. void
  531. vsf_sysdep_adopt_capabilities(unsigned int caps)
  532. {
  533. /* n.b. yes I know I should be using libcap!! */
  534. int retval;
  535. struct __user_cap_header_struct cap_head;
  536. struct __user_cap_data_struct cap_data;
  537. __u32 cap_mask = 0;
  538. if (!caps)
  539. {
  540. bug("asked to adopt no capabilities");
  541. }
  542. vsf_sysutil_memclr(&cap_head, sizeof(cap_head));
  543. vsf_sysutil_memclr(&cap_data, sizeof(cap_data));
  544. cap_head.version = _LINUX_CAPABILITY_VERSION;
  545. cap_head.pid = 0;
  546. if (caps & kCapabilityCAP_CHOWN)
  547. {
  548. cap_mask |= (1 << CAP_CHOWN);
  549. }
  550. if (caps & kCapabilityCAP_NET_BIND_SERVICE)
  551. {
  552. cap_mask |= (1 << CAP_NET_BIND_SERVICE);
  553. }
  554. cap_data.effective = cap_data.permitted = cap_mask;
  555. cap_data.inheritable = 0;
  556. retval = capset(&cap_head, &cap_data);
  557. if (retval != 0)
  558. {
  559. die("capset");
  560. }
  561. }
  562. #else /* VSF_SYSDEP_HAVE_LIBCAP */
  563. static int
  564. do_checkcap(void)
  565. {
  566. cap_t current_caps = cap_get_proc();
  567. cap_free(current_caps);
  568. if (current_caps != NULL)
  569. {
  570. return 1;
  571. }
  572. return 0;
  573. }
  574. void
  575. vsf_sysdep_adopt_capabilities(unsigned int caps)
  576. {
  577. int retval;
  578. cap_value_t cap_value;
  579. cap_t adopt_caps = cap_init();
  580. if (caps & kCapabilityCAP_CHOWN)
  581. {
  582. cap_value = CAP_CHOWN;
  583. cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);
  584. cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);
  585. }
  586. if (caps & kCapabilityCAP_NET_BIND_SERVICE)
  587. {
  588. cap_value = CAP_NET_BIND_SERVICE;
  589. cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);
  590. cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);
  591. }
  592. retval = cap_set_proc(adopt_caps);
  593. if (retval != 0)
  594. {
  595. die("cap_set_proc");
  596. }
  597. cap_free(adopt_caps);
  598. }
  599. #endif /* !VSF_SYSDEP_HAVE_LIBCAP */
  600. #endif /* VSF_SYSDEP_HAVE_CAPABILITIES || VSF_SYSDEP_HAVE_LIBCAP */
  601. int
  602. vsf_sysutil_sendfile(const int out_fd, const int in_fd,
  603. filesize_t* p_offset, filesize_t num_send,
  604. unsigned int max_chunk)
  605. {
  606. /* Grr - why is off_t signed? */
  607. if (*p_offset < 0 || num_send < 0)
  608. {
  609. die("invalid offset or send count in vsf_sysutil_sendfile");
  610. }
  611. if (max_chunk == 0)
  612. {
  613. max_chunk = INT_MAX;
  614. }
  615. while (num_send > 0)
  616. {
  617. int retval;
  618. unsigned int send_this_time;
  619. if (num_send > max_chunk)
  620. {
  621. send_this_time = max_chunk;
  622. }
  623. else
  624. {
  625. send_this_time = (unsigned int) num_send;
  626. }
  627. /* Keep input file position in line with sendfile() calls */
  628. vsf_sysutil_lseek_to(in_fd, *p_offset);
  629. retval = do_sendfile(out_fd, in_fd, send_this_time, *p_offset);
  630. if (vsf_sysutil_retval_is_error(retval) || retval == 0)
  631. {
  632. return retval;
  633. }
  634. num_send -= retval;
  635. *p_offset += retval;
  636. }
  637. return 0;
  638. }
  639. static int do_sendfile(const int out_fd, const int in_fd,
  640. unsigned int num_send, filesize_t start_pos)
  641. {
  642. /* Probably should one day be shared with instance in ftpdataio.c */
  643. static char* p_recvbuf;
  644. unsigned int total_written = 0;
  645. int retval;
  646. enum EVSFSysUtilError error;
  647. (void) start_pos;
  648. (void) error;
  649. #if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || \
  650. defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) || \
  651. defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE) || \
  652. defined(VSF_SYSDEP_HAVE_AIX_SENDFILE) || \
  653. defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  654. if (tunable_use_sendfile)
  655. {
  656. static int s_sendfile_checked;
  657. static int s_runtime_sendfile_works;
  658. if (!s_sendfile_checked || s_runtime_sendfile_works)
  659. {
  660. do
  661. {
  662. #ifdef VSF_SYSDEP_HAVE_LINUX_SENDFILE
  663. retval = sendfile(out_fd, in_fd, NULL, num_send);
  664. #elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE)
  665. {
  666. /* XXX - start_pos will truncate on 32-bit machines - can we
  667. * say "start from current pos"?
  668. */
  669. off_t written = 0;
  670. retval = sendfile(in_fd, out_fd, start_pos, num_send, NULL,
  671. &written, 0);
  672. /* Translate to Linux-like retval */
  673. if (written > 0)
  674. {
  675. retval = (int) written;
  676. }
  677. }
  678. #elif defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)
  679. {
  680. size_t written = 0;
  681. struct sendfilevec the_vec;
  682. vsf_sysutil_memclr(&the_vec, sizeof(the_vec));
  683. the_vec.sfv_fd = in_fd;
  684. the_vec.sfv_off = start_pos;
  685. the_vec.sfv_len = num_send;
  686. retval = sendfilev(out_fd, &the_vec, 1, &written);
  687. /* Translate to Linux-like retval */
  688. if (written > 0)
  689. {
  690. retval = (int) written;
  691. }
  692. }
  693. #elif defined(VSF_SYSDEP_HAVE_AIX_SENDFILE)
  694. {
  695. struct sf_parms sf_iobuf;
  696. vsf_sysutil_memclr(&sf_iobuf, sizeof(sf_iobuf));
  697. sf_iobuf.header_data = NULL;
  698. sf_iobuf.header_length = 0;
  699. sf_iobuf.trailer_data = NULL;
  700. sf_iobuf.trailer_length = 0;
  701. sf_iobuf.file_descriptor = in_fd;
  702. sf_iobuf.file_offset = start_pos;
  703. sf_iobuf.file_bytes = num_send;
  704. retval = send_file((int*)&out_fd, &sf_iobuf, 0);
  705. if (retval >= 0)
  706. {
  707. retval = sf_iobuf.bytes_sent;
  708. }
  709. }
  710. #else /* must be VSF_SYSDEP_HAVE_HPUX_SENDFILE */
  711. {
  712. retval = sendfile(out_fd, in_fd, start_pos, num_send, NULL, 0);
  713. }
  714. #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */
  715. error = vsf_sysutil_get_error();
  716. vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, out_fd);
  717. }
  718. while (vsf_sysutil_retval_is_error(retval) &&
  719. error == kVSFSysUtilErrINTR);
  720. if (!s_sendfile_checked)
  721. {
  722. s_sendfile_checked = 1;
  723. if (!vsf_sysutil_retval_is_error(retval) ||
  724. error != kVSFSysUtilErrNOSYS)
  725. {
  726. s_runtime_sendfile_works = 1;
  727. }
  728. }
  729. if (!vsf_sysutil_retval_is_error(retval))
  730. {
  731. return retval;
  732. }
  733. if (s_runtime_sendfile_works && error != kVSFSysUtilErrINVAL &&
  734. error != kVSFSysUtilErrOPNOTSUPP)
  735. {
  736. return retval;
  737. }
  738. /* Fall thru to normal implementation. We won't check again. NOTE -
  739. * also falls through if sendfile() is OK but it returns EINVAL. For
  740. * Linux this means the file was not page cache backed. Original
  741. * complaint was trying to serve files from an NTFS filesystem!
  742. */
  743. }
  744. }
  745. #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE || VSF_SYSDEP_HAVE_FREEBSD_SENDFILE */
  746. if (p_recvbuf == 0)
  747. {
  748. vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE);
  749. }
  750. while (1)
  751. {
  752. unsigned int num_read;
  753. unsigned int num_written;
  754. unsigned int num_read_this_time = VSFTP_DATA_BUFSIZE;
  755. if (num_read_this_time > num_send)
  756. {
  757. num_read_this_time = num_send;
  758. }
  759. retval = vsf_sysutil_read(in_fd, p_recvbuf, num_read_this_time);
  760. if (retval < 0)
  761. {
  762. return retval;
  763. }
  764. else if (retval == 0)
  765. {
  766. return -1;
  767. }
  768. num_read = (unsigned int) retval;
  769. retval = vsf_sysutil_write_loop(out_fd, p_recvbuf, num_read);
  770. if (retval < 0)
  771. {
  772. return retval;
  773. }
  774. num_written = (unsigned int) retval;
  775. total_written += num_written;
  776. if (num_written != num_read)
  777. {
  778. return num_written;
  779. }
  780. if (num_written > num_send)
  781. {
  782. bug("num_written bigger than num_send in do_sendfile");
  783. }
  784. num_send -= num_written;
  785. if (num_send == 0)
  786. {
  787. /* Bingo! */
  788. return total_written;
  789. }
  790. }
  791. }
  792. void
  793. vsf_sysutil_set_proctitle_prefix(const struct mystr* p_str)
  794. {
  795. str_copy(&s_proctitle_prefix_str, p_str);
  796. }
  797. /* This delegation is common to all setproctitle() implementations */
  798. void
  799. vsf_sysutil_setproctitle_str(const struct mystr* p_str)
  800. {
  801. vsf_sysutil_setproctitle(str_getbuf(p_str));
  802. }
  803. void
  804. vsf_sysutil_setproctitle(const char* p_text)
  805. {
  806. struct mystr proctitle_str = INIT_MYSTR;
  807. str_copy(&proctitle_str, &s_proctitle_prefix_str);
  808. if (!str_isempty(&proctitle_str))
  809. {
  810. str_append_text(&proctitle_str, ": ");
  811. }
  812. str_append_text(&proctitle_str, p_text);
  813. vsf_sysutil_setproctitle_internal(str_getbuf(&proctitle_str));
  814. str_free(&proctitle_str);
  815. }
  816. #ifdef VSF_SYSDEP_HAVE_SETPROCTITLE
  817. void
  818. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  819. {
  820. (void) argc;
  821. (void) argv;
  822. }
  823. void
  824. vsf_sysutil_setproctitle_internal(const char* p_buf)
  825. {
  826. setproctitle("%s", p_buf);
  827. }
  828. #elif defined(VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE)
  829. void
  830. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  831. {
  832. (void) argc;
  833. (void) argv;
  834. }
  835. void
  836. vsf_sysutil_setproctitle_internal(const char* p_buf)
  837. {
  838. struct mystr proctitle_str = INIT_MYSTR;
  839. union pstun p;
  840. str_alloc_text(&proctitle_str, "ftpz: ");
  841. str_append_text(&proctitle_str, p_buf);
  842. p.pst_command = str_getbuf(&proctitle_str);
  843. pstat(PSTAT_SETCMD, p, 0, 0, 0);
  844. str_free(&proctitle_str);
  845. }
  846. #elif defined(VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK)
  847. void
  848. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  849. {
  850. int i;
  851. char** p_env = environ;
  852. if (s_proctitle_inited)
  853. {
  854. bug("sysutil_setproctitle_init called twice");
  855. }
  856. s_proctitle_inited = 1;
  857. if (argv[0] == 0)
  858. {
  859. die("no argv[0] in sysutil_setproctitle_init");
  860. }
  861. for (i=0; i<argc; i++)
  862. {
  863. s_proctitle_space += vsf_sysutil_strlen(argv[i]) + 1;
  864. if (i > 0)
  865. {
  866. argv[i] = 0;
  867. }
  868. }
  869. while (*p_env != 0)
  870. {
  871. s_proctitle_space += vsf_sysutil_strlen(*p_env) + 1;
  872. p_env++;
  873. }
  874. /* Oops :-) */
  875. environ = 0;
  876. s_p_proctitle = (char*) argv[0];
  877. vsf_sysutil_memclr(s_p_proctitle, s_proctitle_space);
  878. }
  879. void
  880. vsf_sysutil_setproctitle_internal(const char* p_buf)
  881. {
  882. struct mystr proctitle_str = INIT_MYSTR;
  883. unsigned int to_copy;
  884. if (!s_proctitle_inited)
  885. {
  886. bug("sysutil_setproctitle: not initialized");
  887. }
  888. vsf_sysutil_memclr(s_p_proctitle, s_proctitle_space);
  889. if (s_proctitle_space < 32)
  890. {
  891. return;
  892. }
  893. str_alloc_text(&proctitle_str, "ftpz: ");
  894. str_append_text(&proctitle_str, p_buf);
  895. to_copy = str_getlen(&proctitle_str);
  896. if (to_copy > s_proctitle_space - 1)
  897. {
  898. to_copy = s_proctitle_space - 1;
  899. }
  900. vsf_sysutil_memcpy(s_p_proctitle, str_getbuf(&proctitle_str), to_copy);
  901. str_free(&proctitle_str);
  902. s_p_proctitle[to_copy] = '\0';
  903. }
  904. #else /* VSF_SYSDEP_HAVE_SETPROCTITLE */
  905. void
  906. vsf_sysutil_setproctitle_init(int argc, const char* argv[])
  907. {
  908. (void) argc;
  909. (void) argv;
  910. }
  911. void
  912. vsf_sysutil_setproctitle_internal(const char* p_buf)
  913. {
  914. (void) p_buf;
  915. }
  916. #endif /* VSF_SYSDEP_HAVE_SETPROCTITLE */
  917. #ifdef VSF_SYSDEP_HAVE_MAP_ANON
  918. void
  919. vsf_sysutil_map_anon_pages_init(void)
  920. {
  921. }
  922. void*
  923. vsf_sysutil_map_anon_pages(unsigned int length)
  924. {
  925. char* retval = mmap(0, length, PROT_READ | PROT_WRITE,
  926. MAP_PRIVATE | MAP_ANON, -1, 0);
  927. if (retval == MAP_FAILED)
  928. {
  929. die("mmap");
  930. }
  931. return retval;
  932. }
  933. #else /* VSF_SYSDEP_HAVE_MAP_ANON */
  934. void
  935. vsf_sysutil_map_anon_pages_init(void)
  936. {
  937. if (s_zero_fd != -1)
  938. {
  939. bug("sysutil_map_anon_pages_init called twice");
  940. }
  941. s_zero_fd = open("/dev/zero", O_RDWR);
  942. if (s_zero_fd < 0)
  943. {
  944. die("could not open /dev/zero");
  945. }
  946. }
  947. void*
  948. vsf_sysutil_map_anon_pages(unsigned int length)
  949. {
  950. char* retval = mmap(0, length, PROT_READ | PROT_WRITE,
  951. MAP_PRIVATE, s_zero_fd, 0);
  952. if (retval == MAP_FAILED)
  953. {
  954. die("mmap");
  955. }
  956. return retval;
  957. }
  958. #endif /* VSF_SYSDEP_HAVE_MAP_ANON */
  959. #ifndef VSF_SYSDEP_NEED_OLD_FD_PASSING
  960. void
  961. vsf_sysutil_send_fd(int sock_fd, int send_fd)
  962. {
  963. int retval;
  964. struct msghdr msg;
  965. struct cmsghdr* p_cmsg;
  966. struct iovec vec;
  967. char cmsgbuf[CMSG_SPACE(sizeof(send_fd))];
  968. int* p_fds;
  969. char sendchar = 0;
  970. msg.msg_control = cmsgbuf;
  971. msg.msg_controllen = sizeof(cmsgbuf);
  972. p_cmsg = CMSG_FIRSTHDR(&msg);
  973. p_cmsg->cmsg_level = SOL_SOCKET;
  974. p_cmsg->cmsg_type = SCM_RIGHTS;
  975. p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
  976. p_fds = (int*)CMSG_DATA(p_cmsg);
  977. *p_fds = send_fd;
  978. msg.msg_controllen = p_cmsg->cmsg_len;
  979. msg.msg_name = NULL;
  980. msg.msg_namelen = 0;
  981. msg.msg_iov = &vec;
  982. msg.msg_iovlen = 1;
  983. msg.msg_flags = 0;
  984. /* "To pass file descriptors or credentials you need to send/read at
  985. * least on byte" (man 7 unix)
  986. */
  987. vec.iov_base = &sendchar;
  988. vec.iov_len = sizeof(sendchar);
  989. retval = sendmsg(sock_fd, &msg, 0);
  990. if (retval != 1)
  991. {
  992. die("sendmsg");
  993. }
  994. }
  995. int
  996. vsf_sysutil_recv_fd(const int sock_fd)
  997. {
  998. int retval;
  999. struct msghdr msg;
  1000. char recvchar;
  1001. struct iovec vec;
  1002. int recv_fd;
  1003. char cmsgbuf[CMSG_SPACE(sizeof(recv_fd))];
  1004. struct cmsghdr* p_cmsg;
  1005. int* p_fd;
  1006. vec.iov_base = &recvchar;
  1007. vec.iov_len = sizeof(recvchar);
  1008. msg.msg_name = NULL;
  1009. msg.msg_namelen = 0;
  1010. msg.msg_iov = &vec;
  1011. msg.msg_iovlen = 1;
  1012. msg.msg_control = cmsgbuf;
  1013. msg.msg_controllen = sizeof(cmsgbuf);
  1014. msg.msg_flags = 0;
  1015. /* In case something goes wrong, set the fd to -1 before the syscall */
  1016. p_fd = (int*)CMSG_DATA(CMSG_FIRSTHDR(&msg));
  1017. *p_fd = -1;
  1018. retval = recvmsg(sock_fd, &msg, 0);
  1019. if (retval != 1)
  1020. {
  1021. die("recvmsg");
  1022. }
  1023. p_cmsg = CMSG_FIRSTHDR(&msg);
  1024. if (p_cmsg == NULL)
  1025. {
  1026. die("no passed fd");
  1027. }
  1028. /* We used to verify the returned cmsg_level, cmsg_type and cmsg_len here,
  1029. * but Linux 2.0 totally uselessly fails to fill these in.
  1030. */
  1031. p_fd = (int*)CMSG_DATA(p_cmsg);
  1032. recv_fd = *p_fd;
  1033. if (recv_fd == -1)
  1034. {
  1035. die("no passed fd");
  1036. }
  1037. return recv_fd;
  1038. }
  1039. #else /* !VSF_SYSDEP_NEED_OLD_FD_PASSING */
  1040. void
  1041. vsf_sysutil_send_fd(int sock_fd, int send_fd)
  1042. {
  1043. int retval;
  1044. char send_char = 0;
  1045. struct msghdr msg;
  1046. struct iovec vec;
  1047. vec.iov_base = &send_char;
  1048. vec.iov_len = 1;
  1049. msg.msg_name = NULL;
  1050. msg.msg_namelen = 0;
  1051. msg.msg_iov = &vec;
  1052. msg.msg_iovlen = 1;
  1053. msg.msg_accrights = (caddr_t) &send_fd;
  1054. msg.msg_accrightslen = sizeof(send_fd);
  1055. retval = sendmsg(sock_fd, &msg, 0);
  1056. if (retval != 1)
  1057. {
  1058. die("sendmsg");
  1059. }
  1060. }
  1061. int
  1062. vsf_sysutil_recv_fd(int sock_fd)
  1063. {
  1064. int retval;
  1065. struct msghdr msg;
  1066. struct iovec vec;
  1067. char recv_char;
  1068. int recv_fd = -1;
  1069. vec.iov_base = &recv_char;
  1070. vec.iov_len = 1;
  1071. msg.msg_name = NULL;
  1072. msg.msg_namelen = 0;
  1073. msg.msg_iov = &vec;
  1074. msg.msg_iovlen = 1;
  1075. msg.msg_accrights = (caddr_t) &recv_fd;
  1076. msg.msg_accrightslen = sizeof(recv_fd);
  1077. retval = recvmsg(sock_fd, &msg, 0);
  1078. if (retval != 1)
  1079. {
  1080. die("recvmsg");
  1081. }
  1082. if (recv_fd == -1)
  1083. {
  1084. die("no passed fd");
  1085. }
  1086. return recv_fd;
  1087. }
  1088. #endif /* !VSF_SYSDEP_NEED_OLD_FD_PASSING */
  1089. #ifndef VSF_SYSDEP_HAVE_UTMPX
  1090. void
  1091. vsf_insert_uwtmp(const struct mystr* p_user_str,
  1092. const struct mystr* p_host_str)
  1093. {
  1094. (void) p_user_str;
  1095. (void) p_host_str;
  1096. }
  1097. void
  1098. vsf_remove_uwtmp(void)
  1099. {
  1100. }
  1101. #else /* !VSF_SYSDEP_HAVE_UTMPX */
  1102. /* IMHO, the pam_unix module REALLY should be doing this in its SM component */
  1103. /* Statics */
  1104. static int s_uwtmp_inserted;
  1105. static struct utmpx s_utent;
  1106. void
  1107. vsf_insert_uwtmp(const struct mystr* p_user_str,
  1108. const struct mystr* p_host_str)
  1109. {
  1110. if (sizeof(s_utent.ut_line) < 16)
  1111. {
  1112. return;
  1113. }
  1114. if (s_uwtmp_inserted)
  1115. {
  1116. bug("insert_uwtmp");
  1117. }
  1118. {
  1119. struct mystr line_str = INIT_MYSTR;
  1120. str_alloc_text(&line_str, "ftpz:");
  1121. str_append_ulong(&line_str, vsf_sysutil_getpid());
  1122. if (str_getlen(&line_str) >= sizeof(s_utent.ut_line))
  1123. {
  1124. str_free(&line_str);
  1125. return;
  1126. }
  1127. vsf_sysutil_strcpy(s_utent.ut_line, str_getbuf(&line_str),
  1128. sizeof(s_utent.ut_line));
  1129. str_free(&line_str);
  1130. }
  1131. s_uwtmp_inserted = 1;
  1132. s_utent.ut_type = USER_PROCESS;
  1133. s_utent.ut_pid = vsf_sysutil_getpid();
  1134. vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str),
  1135. sizeof(s_utent.ut_user));
  1136. vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str),
  1137. sizeof(s_utent.ut_host));
  1138. s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec();
  1139. setutxent();
  1140. (void) pututxline(&s_utent);
  1141. endutxent();
  1142. updwtmpx(WTMPX_FILE, &s_utent);
  1143. }
  1144. void
  1145. vsf_remove_uwtmp(void)
  1146. {
  1147. if (!s_uwtmp_inserted)
  1148. {
  1149. return;
  1150. }
  1151. s_uwtmp_inserted = 0;
  1152. s_utent.ut_type = DEAD_PROCESS;
  1153. vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user));
  1154. vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host));
  1155. s_utent.ut_tv.tv_sec = 0;
  1156. setutxent();
  1157. (void) pututxline(&s_utent);
  1158. endutxent();
  1159. s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec();
  1160. updwtmpx(WTMPX_FILE, &s_utent);
  1161. }
  1162. #endif /* !VSF_SYSDEP_HAVE_UTMPX */
  1163. void
  1164. vsf_set_die_if_parent_dies()
  1165. {
  1166. #ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG
  1167. if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) != 0)
  1168. {
  1169. die("prctl");
  1170. }
  1171. #endif
  1172. }
  1173. void
  1174. vsf_set_term_if_parent_dies()
  1175. {
  1176. #ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG
  1177. if (prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) != 0)
  1178. {
  1179. die("prctl");
  1180. }
  1181. #endif
  1182. }
  1183. int
  1184. vsf_sysutil_fork_isolate_all_failok()
  1185. {
  1186. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1187. static int cloneflags_work = 1;
  1188. if (cloneflags_work)
  1189. {
  1190. int ret = syscall(__NR_clone,
  1191. CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNET | SIGCHLD,
  1192. NULL);
  1193. if (ret != -1 || (errno != EINVAL && errno != EPERM))
  1194. {
  1195. if (ret == 0)
  1196. {
  1197. vsf_sysutil_post_fork();
  1198. }
  1199. return ret;
  1200. }
  1201. cloneflags_work = 0;
  1202. }
  1203. #endif
  1204. return vsf_sysutil_fork_isolate_failok();
  1205. }
  1206. int
  1207. vsf_sysutil_fork_isolate_failok()
  1208. {
  1209. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1210. static int cloneflags_work = 1;
  1211. if (cloneflags_work)
  1212. {
  1213. int ret = syscall(__NR_clone, CLONE_NEWPID | CLONE_NEWIPC | SIGCHLD, NULL);
  1214. if (ret != -1 || (errno != EINVAL && errno != EPERM))
  1215. {
  1216. if (ret == 0)
  1217. {
  1218. vsf_sysutil_post_fork();
  1219. }
  1220. return ret;
  1221. }
  1222. cloneflags_work = 0;
  1223. }
  1224. #endif
  1225. return vsf_sysutil_fork_failok();
  1226. }
  1227. int
  1228. vsf_sysutil_fork_newnet()
  1229. {
  1230. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1231. static int cloneflags_work = 1;
  1232. if (cloneflags_work)
  1233. {
  1234. int ret = syscall(__NR_clone, CLONE_NEWNET | SIGCHLD, NULL);
  1235. if (ret != -1 || (errno != EINVAL && errno != EPERM))
  1236. {
  1237. if (ret == 0)
  1238. {
  1239. vsf_sysutil_post_fork();
  1240. }
  1241. return ret;
  1242. }
  1243. cloneflags_work = 0;
  1244. }
  1245. #endif
  1246. return vsf_sysutil_fork();
  1247. }
  1248. int
  1249. vsf_sysutil_getpid_nocache(void)
  1250. {
  1251. #ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
  1252. /* Need to defeat the glibc pid caching because we need to hit a raw
  1253. * sys_clone() above.
  1254. */
  1255. return syscall(__NR_getpid);
  1256. #else
  1257. return getpid();
  1258. #endif
  1259. }