pid.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. pid.c
  9. Abstract:
  10. This module implements C library functionality loosely tied to process and
  11. thread IDs.
  12. Author:
  13. Evan Green 30-Mar-2013
  14. Environment:
  15. User Mode C Library.
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "libcp.h"
  21. #include <stdio.h>
  22. #include <unistd.h>
  23. #include <errno.h>
  24. //
  25. // ---------------------------------------------------------------- Definitions
  26. //
  27. //
  28. // ------------------------------------------------------ Data Type Definitions
  29. //
  30. //
  31. // ----------------------------------------------- Internal Function Prototypes
  32. //
  33. //
  34. // -------------------------------------------------------------------- Globals
  35. //
  36. //
  37. // TODO: These should be thread local.
  38. //
  39. BOOL ClThreadIdentityValid;
  40. THREAD_IDENTITY ClThreadIdentity;
  41. //
  42. // ------------------------------------------------------------------ Functions
  43. //
  44. LIBC_API
  45. pid_t
  46. getpid (
  47. void
  48. )
  49. /*++
  50. Routine Description:
  51. This routine returns the current process identifier.
  52. Arguments:
  53. None.
  54. Return Value:
  55. Returns the process identifier.
  56. --*/
  57. {
  58. PROCESS_ID ProcessId;
  59. KSTATUS Status;
  60. ProcessId = 0;
  61. Status = OsGetProcessId(ProcessIdProcess, &ProcessId);
  62. ASSERT(KSUCCESS(Status));
  63. return ProcessId;
  64. }
  65. LIBC_API
  66. pid_t
  67. getppid (
  68. void
  69. )
  70. /*++
  71. Routine Description:
  72. This routine returns the current process' parent process identifier.
  73. Arguments:
  74. None.
  75. Return Value:
  76. Returns the parent process identifier.
  77. --*/
  78. {
  79. PROCESS_ID ProcessId;
  80. KSTATUS Status;
  81. ProcessId = 0;
  82. Status = OsGetProcessId(ProcessIdParentProcess, &ProcessId);
  83. ASSERT(KSUCCESS(Status));
  84. return ProcessId;
  85. }
  86. LIBC_API
  87. pid_t
  88. getpgid (
  89. pid_t ProcessId
  90. )
  91. /*++
  92. Routine Description:
  93. This routine returns the process group identifier of the process with
  94. the given ID, or the calling process.
  95. Arguments:
  96. ProcessId - Supplies the process ID to return the process group for. Supply
  97. 0 to return the process group ID of the calling process.
  98. Return Value:
  99. Returns the process group ID of the given process (or the current process).
  100. (pid_t)-1 and errno will be set to EPERM if the desired process is out of
  101. this session and the implementation doesn't allow cross session requests,
  102. ESRCH if no such process exists, or EINVAL if the pid argument is invalid.
  103. --*/
  104. {
  105. PROCESS_ID Result;
  106. KSTATUS Status;
  107. Result = ProcessId;
  108. Status = OsGetProcessId(ProcessIdProcessGroup, &Result);
  109. if (!KSUCCESS(Status)) {
  110. errno = ClConvertKstatusToErrorNumber(Status);
  111. return (pid_t)-1;
  112. }
  113. return Result;
  114. }
  115. LIBC_API
  116. pid_t
  117. getpgrp (
  118. void
  119. )
  120. /*++
  121. Routine Description:
  122. This routine returns the process group identifier of the calling process.
  123. Arguments:
  124. None.
  125. Return Value:
  126. Returns the process group ID of the calling process.
  127. --*/
  128. {
  129. return getpgid(0);
  130. }
  131. LIBC_API
  132. int
  133. setpgid (
  134. pid_t ProcessId,
  135. pid_t ProcessGroupId
  136. )
  137. /*++
  138. Routine Description:
  139. This routine joins an existing process group or creates a new process group
  140. within the session of the calling process. The process group ID of a
  141. session leader will not change.
  142. Arguments:
  143. ProcessId - Supplies the process ID of the process to put in a new process
  144. group. Supply 0 to use the current process.
  145. ProcessGroupId - Supplies the new process group to put the process in.
  146. Supply zero to set the process group ID to the same numerical value as
  147. the specified process ID.
  148. Return Value:
  149. 0 on success.
  150. -1 on failure and errno will be set to contain more information.
  151. --*/
  152. {
  153. KSTATUS Status;
  154. Status = OsSetProcessId(ProcessIdProcessGroup, ProcessId, ProcessGroupId);
  155. if (!KSUCCESS(Status)) {
  156. errno = ClConvertKstatusToErrorNumber(Status);
  157. return -1;
  158. }
  159. return 0;
  160. }
  161. LIBC_API
  162. pid_t
  163. setpgrp (
  164. void
  165. )
  166. /*++
  167. Routine Description:
  168. This routine sets the process group ID of the calling process to the
  169. process ID of the calling process. This routine has no effect if the
  170. calling process is a session leader.
  171. Arguments:
  172. None.
  173. Return Value:
  174. Returns the process group ID of the calling process.
  175. --*/
  176. {
  177. setpgid(0, 0);
  178. return getpgid(0);
  179. }
  180. LIBC_API
  181. pid_t
  182. getsid (
  183. pid_t ProcessId
  184. )
  185. /*++
  186. Routine Description:
  187. This routine returns the process group ID of the process that is the
  188. session leader of the given process. If the given parameter is 0, then
  189. the current process ID is used as the parameter.
  190. Arguments:
  191. ProcessId - Supplies a process ID of the process whose session leader
  192. should be returned.
  193. Return Value:
  194. Returns the process group ID of the session leader of the specified process.
  195. -1 on failure, and errno will be set to contain more information.
  196. --*/
  197. {
  198. PROCESS_ID Result;
  199. KSTATUS Status;
  200. Result = ProcessId;
  201. Status = OsGetProcessId(ProcessIdSession, &Result);
  202. if (!KSUCCESS(Status)) {
  203. errno = ClConvertKstatusToErrorNumber(Status);
  204. return (pid_t)-1;
  205. }
  206. return Result;
  207. }
  208. LIBC_API
  209. pid_t
  210. setsid (
  211. void
  212. )
  213. /*++
  214. Routine Description:
  215. This routine creates a new session if the calling process is not a
  216. process group leader. The calling process will be the session leader of
  217. the new session, and will be the process group leader of a new process
  218. group, and will have no controlling terminal. The process group ID of the
  219. calling process will be set equal to the process ID of the calling process.
  220. The calling process will be the only process in the new process group and
  221. the only process in the new session.
  222. Arguments:
  223. None.
  224. Return Value:
  225. Returns the value of the new process group ID of the calling process.
  226. -1 on failure, and errno will be set to contain more information.
  227. --*/
  228. {
  229. KSTATUS Status;
  230. Status = OsSetProcessId(ProcessIdSession, 0, 0);
  231. if (!KSUCCESS(Status)) {
  232. errno = ClConvertKstatusToErrorNumber(Status);
  233. return -1;
  234. }
  235. return getpgid(0);
  236. }
  237. LIBC_API
  238. pid_t
  239. fork (
  240. void
  241. )
  242. /*++
  243. Routine Description:
  244. This routine creates a new process by copying the existing process.
  245. Arguments:
  246. None.
  247. Return Value:
  248. Returns 0 to the child process.
  249. Returns the process ID of the child process to the parent process.
  250. Returns -1 to the parent process on error, and the errno variable will be
  251. set to provide more information about the error.
  252. --*/
  253. {
  254. INTN Result;
  255. ClpRunAtforkPrepareRoutines();
  256. fflush(NULL);
  257. Result = OsForkProcess(0, NULL);
  258. if (Result == 0) {
  259. ClpRunAtforkChildRoutines();
  260. //
  261. // Call the parent at-fork routines even on failure so that at least the
  262. // mutex is unlocked.
  263. //
  264. } else {
  265. ClpRunAtforkParentRoutines();
  266. }
  267. if (Result >= 0) {
  268. return Result;
  269. }
  270. errno = ClConvertKstatusToErrorNumber(Result);
  271. return -1;
  272. }
  273. LIBC_API
  274. uid_t
  275. getuid (
  276. void
  277. )
  278. /*++
  279. Routine Description:
  280. This routine returns the current real user ID.
  281. Arguments:
  282. None.
  283. Return Value:
  284. Returns the real user ID.
  285. --*/
  286. {
  287. KSTATUS Status;
  288. if (ClThreadIdentityValid == FALSE) {
  289. Status = OsSetThreadIdentity(0, &ClThreadIdentity);
  290. if (!KSUCCESS(Status)) {
  291. return -1;
  292. }
  293. ClThreadIdentityValid = TRUE;
  294. }
  295. return ClThreadIdentity.RealUserId;
  296. }
  297. LIBC_API
  298. gid_t
  299. getgid (
  300. void
  301. )
  302. /*++
  303. Routine Description:
  304. This routine returns the current real group ID.
  305. Arguments:
  306. None.
  307. Return Value:
  308. Returns the real group ID.
  309. --*/
  310. {
  311. KSTATUS Status;
  312. if (ClThreadIdentityValid == FALSE) {
  313. Status = OsSetThreadIdentity(0, &ClThreadIdentity);
  314. if (!KSUCCESS(Status)) {
  315. return -1;
  316. }
  317. ClThreadIdentityValid = TRUE;
  318. }
  319. return ClThreadIdentity.RealGroupId;
  320. }
  321. LIBC_API
  322. uid_t
  323. geteuid (
  324. void
  325. )
  326. /*++
  327. Routine Description:
  328. This routine returns the current effective user ID, which represents the
  329. privilege level with which this process can perform operations. Normally
  330. this is the same as the real user ID, but binaries with the setuid
  331. permission bit set the effective user ID to their own when they're run.
  332. Arguments:
  333. None.
  334. Return Value:
  335. Returns the effective user ID.
  336. --*/
  337. {
  338. KSTATUS Status;
  339. if (ClThreadIdentityValid == FALSE) {
  340. Status = OsSetThreadIdentity(0, &ClThreadIdentity);
  341. if (!KSUCCESS(Status)) {
  342. return -1;
  343. }
  344. ClThreadIdentityValid = TRUE;
  345. }
  346. return ClThreadIdentity.EffectiveUserId;
  347. }
  348. LIBC_API
  349. gid_t
  350. getegid (
  351. void
  352. )
  353. /*++
  354. Routine Description:
  355. This routine returns the current effective group ID, which represents the
  356. privilege level with which this process can perform operations. Normally
  357. this is the same as the real group ID, but binaries with the setgid
  358. permission bit set the effective group ID to their own when they're run.
  359. Arguments:
  360. None.
  361. Return Value:
  362. Returns the effective group ID.
  363. --*/
  364. {
  365. KSTATUS Status;
  366. if (ClThreadIdentityValid == FALSE) {
  367. Status = OsSetThreadIdentity(0, &ClThreadIdentity);
  368. if (!KSUCCESS(Status)) {
  369. return -1;
  370. }
  371. ClThreadIdentityValid = TRUE;
  372. }
  373. return ClThreadIdentity.EffectiveGroupId;
  374. }
  375. LIBC_API
  376. int
  377. setuid (
  378. uid_t UserId
  379. )
  380. /*++
  381. Routine Description:
  382. This routine sets the real user ID, effective user ID, and saved
  383. set-user-ID of the calling process to the given user ID. This only occurs
  384. if the process has the appropriate privileges to do this. If the process
  385. does not have appropriate privileges but the given user ID is equal to the
  386. real user ID or the saved set-user-ID, then this routine sets the effective
  387. user ID to the given user ID; the real user ID and saved set-user-ID remain
  388. unchanged.
  389. Arguments:
  390. UserId - Supplies the user ID to change to.
  391. Return Value:
  392. 0 on success.
  393. -1 on failure, and errno will be set to contain more information. Common
  394. errors include EINVAL if the user ID is not valid, and EPERM if the
  395. process does not have appropriate privileges and the given ID does not
  396. match the real user ID or saved set-user-ID.
  397. --*/
  398. {
  399. ULONG Fields;
  400. KSTATUS Status;
  401. ClThreadIdentity.RealUserId = UserId;
  402. ClThreadIdentity.EffectiveUserId = UserId;
  403. ClThreadIdentity.SavedUserId = UserId;
  404. Fields = THREAD_IDENTITY_FIELD_REAL_USER_ID |
  405. THREAD_IDENTITY_FIELD_EFFECTIVE_USER_ID |
  406. THREAD_IDENTITY_FIELD_SAVED_USER_ID;
  407. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  408. if (!KSUCCESS(Status)) {
  409. ClThreadIdentityValid = FALSE;
  410. errno = ClConvertKstatusToErrorNumber(Status);
  411. return -1;
  412. }
  413. ClThreadIdentityValid = TRUE;
  414. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  415. return 0;
  416. }
  417. LIBC_API
  418. int
  419. setgid (
  420. gid_t GroupId
  421. )
  422. /*++
  423. Routine Description:
  424. This routine sets the real group ID, effective group ID, and saved
  425. set-group-ID of the calling process to the given group ID. This only occurs
  426. if the process has the appropriate privileges to do this. If the process
  427. does not have appropriate privileges but the given group ID is equal to the
  428. real group ID or the saved set-group-ID, then this routine sets the
  429. effective group ID to the given group ID; the real group ID and saved
  430. set-group-ID remain unchanged.
  431. Arguments:
  432. GroupId - Supplies the group ID to change to.
  433. Return Value:
  434. 0 on success.
  435. -1 on failure, and errno will be set to contain more information. Common
  436. errors include EINVAL if the group ID is not valid, and EPERM if the
  437. process does not have appropriate privileges and the given ID does not
  438. match the real group ID or saved set-group-ID.
  439. --*/
  440. {
  441. ULONG Fields;
  442. KSTATUS Status;
  443. ClThreadIdentity.RealGroupId = GroupId;
  444. ClThreadIdentity.EffectiveGroupId = GroupId;
  445. ClThreadIdentity.SavedGroupId = GroupId;
  446. Fields = THREAD_IDENTITY_FIELD_REAL_GROUP_ID |
  447. THREAD_IDENTITY_FIELD_EFFECTIVE_GROUP_ID |
  448. THREAD_IDENTITY_FIELD_SAVED_GROUP_ID;
  449. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  450. if (!KSUCCESS(Status)) {
  451. ClThreadIdentityValid = FALSE;
  452. errno = ClConvertKstatusToErrorNumber(Status);
  453. return -1;
  454. }
  455. ClThreadIdentityValid = TRUE;
  456. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  457. return 0;
  458. }
  459. LIBC_API
  460. int
  461. seteuid (
  462. uid_t UserId
  463. )
  464. /*++
  465. Routine Description:
  466. This routine sets the effective user ID of the calling process to the given
  467. user ID. The real user ID and saved set-user-ID remain unchanged. This only
  468. occurs if the process has appropriate privileges, or if the real user ID
  469. is equal to the saved set-user-ID.
  470. Arguments:
  471. UserId - Supplies the effective user ID to change to.
  472. Return Value:
  473. 0 on success.
  474. -1 on failure, and errno will be set to contain more information. Common
  475. errors include EINVAL if the user ID is not valid, and EPERM if the
  476. process does not have appropriate privileges and the given ID does not
  477. match the real user ID or saved set-user-ID.
  478. --*/
  479. {
  480. ULONG Fields;
  481. KSTATUS Status;
  482. ClThreadIdentity.EffectiveUserId = UserId;
  483. Fields = THREAD_IDENTITY_FIELD_EFFECTIVE_USER_ID;
  484. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  485. if (!KSUCCESS(Status)) {
  486. ClThreadIdentityValid = FALSE;
  487. errno = ClConvertKstatusToErrorNumber(Status);
  488. return -1;
  489. }
  490. ClThreadIdentityValid = TRUE;
  491. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  492. return 0;
  493. }
  494. LIBC_API
  495. int
  496. setegid (
  497. gid_t GroupId
  498. )
  499. /*++
  500. Routine Description:
  501. This routine sets the effective group ID of the calling process to the
  502. given group ID. The real group ID and saved set-group-ID remain unchanged.
  503. This only occurs if the process has appropriate privileges, or if the real
  504. group ID is equal to the saved set-group-ID.
  505. Arguments:
  506. GroupId - Supplies the effective group ID to change to.
  507. Return Value:
  508. 0 on success.
  509. -1 on failure, and errno will be set to contain more information. Common
  510. errors include EINVAL if the group ID is not valid, and EPERM if the
  511. process does not have appropriate privileges and the given ID does not
  512. match the real group ID or saved set-group-ID.
  513. --*/
  514. {
  515. ULONG Fields;
  516. KSTATUS Status;
  517. ClThreadIdentity.EffectiveGroupId = GroupId;
  518. Fields = THREAD_IDENTITY_FIELD_EFFECTIVE_GROUP_ID;
  519. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  520. if (!KSUCCESS(Status)) {
  521. ClThreadIdentityValid = FALSE;
  522. errno = ClConvertKstatusToErrorNumber(Status);
  523. return -1;
  524. }
  525. ClThreadIdentityValid = TRUE;
  526. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  527. return 0;
  528. }
  529. LIBC_API
  530. int
  531. setreuid (
  532. uid_t RealUserId,
  533. uid_t EffectiveUserId
  534. )
  535. /*++
  536. Routine Description:
  537. This routine sets the real and/or effective user IDs of the current process
  538. to the given values. This only occurs if the process has appropriate
  539. privileges. Unprivileged processes may only set the effective user ID to
  540. the real or saved user IDs. Unprivileged users may only set the real
  541. group ID to the saved or effective user IDs. If the real user ID is being
  542. set, or the effective user ID is being set to something other than the
  543. previous real user ID, then the saved user ID is also set to the new
  544. effective user ID.
  545. Arguments:
  546. RealUserId - Supplies the real user ID to change to. If -1 is supplied, the
  547. real user ID will not be changed.
  548. EffectiveUserId - Supplies the effective user ID to change to. If -1 is
  549. supplied, the effective user ID will not be changed.
  550. Return Value:
  551. 0 on success.
  552. -1 on failure, and errno will be set to contain more information. Common
  553. errors include EINVAL if a user ID is not valid, and EPERM if the
  554. process does not have appropriate privileges and the given effective ID
  555. does not match the real user ID or saved set-user-ID.
  556. --*/
  557. {
  558. ULONG Fields;
  559. KSTATUS Status;
  560. Fields = 0;
  561. //
  562. // First just get the identity.
  563. //
  564. if (ClThreadIdentityValid == FALSE) {
  565. Status = OsSetThreadIdentity(0, &ClThreadIdentity);
  566. if (!KSUCCESS(Status)) {
  567. return -1;
  568. }
  569. ClThreadIdentityValid = TRUE;
  570. }
  571. ClThreadIdentity.EffectiveUserId = EffectiveUserId;
  572. if (EffectiveUserId != (uid_t)-1) {
  573. Fields |= THREAD_IDENTITY_FIELD_EFFECTIVE_USER_ID;
  574. if (EffectiveUserId != ClThreadIdentity.RealUserId) {
  575. ClThreadIdentity.SavedUserId = ClThreadIdentity.EffectiveUserId;
  576. Fields |= THREAD_IDENTITY_FIELD_SAVED_USER_ID;
  577. }
  578. }
  579. ClThreadIdentity.RealUserId = RealUserId;
  580. if (RealUserId != (uid_t)-1) {
  581. ClThreadIdentity.SavedUserId = ClThreadIdentity.EffectiveUserId;
  582. Fields |= THREAD_IDENTITY_FIELD_REAL_USER_ID |
  583. THREAD_IDENTITY_FIELD_EFFECTIVE_USER_ID;
  584. }
  585. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  586. if (!KSUCCESS(Status)) {
  587. ClThreadIdentityValid = FALSE;
  588. errno = ClConvertKstatusToErrorNumber(Status);
  589. return -1;
  590. }
  591. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  592. return 0;
  593. }
  594. LIBC_API
  595. int
  596. setregid (
  597. gid_t RealGroupId,
  598. gid_t EffectiveGroupId
  599. )
  600. /*++
  601. Routine Description:
  602. This routine sets the real and/or effective group IDs of the current process
  603. to the given values. This only occurs if the process has appropriate
  604. privileges. Unprivileged processes may only set the effective group ID to
  605. the real or saved group IDs. Unprivileged users may only set the real
  606. group ID to the saved or effective group IDs. If the real group ID is being
  607. set, or the effective group ID is being set to something other than the
  608. previous real group ID, then the saved group ID is also set to the new
  609. effective group ID.
  610. Arguments:
  611. RealGroupId - Supplies the real group ID to change to. If -1 is supplied,
  612. the real group ID will not be changed.
  613. EffectiveGroupId - Supplies the effective group ID to change to. If -1 is
  614. supplied, the effective group ID will not be changed.
  615. Return Value:
  616. 0 on success.
  617. -1 on failure, and errno will be set to contain more information. Common
  618. errors include EINVAL if a group ID is not valid, and EPERM if the
  619. process does not have appropriate privileges and the given effective ID
  620. does not match the real group ID or saved set-group-ID.
  621. --*/
  622. {
  623. ULONG Fields;
  624. KSTATUS Status;
  625. Fields = 0;
  626. //
  627. // First just get the identity.
  628. //
  629. if (ClThreadIdentityValid == FALSE) {
  630. Status = OsSetThreadIdentity(0, &ClThreadIdentity);
  631. if (!KSUCCESS(Status)) {
  632. return -1;
  633. }
  634. ClThreadIdentityValid = TRUE;
  635. }
  636. ClThreadIdentity.EffectiveGroupId = EffectiveGroupId;
  637. if (EffectiveGroupId != (gid_t)-1) {
  638. Fields |= THREAD_IDENTITY_FIELD_EFFECTIVE_GROUP_ID;
  639. if (EffectiveGroupId != ClThreadIdentity.RealGroupId) {
  640. ClThreadIdentity.SavedGroupId = ClThreadIdentity.EffectiveGroupId;
  641. Fields |= THREAD_IDENTITY_FIELD_SAVED_GROUP_ID;
  642. }
  643. }
  644. ClThreadIdentity.RealGroupId = RealGroupId;
  645. if (RealGroupId != (gid_t)-1) {
  646. ClThreadIdentity.SavedGroupId = ClThreadIdentity.EffectiveGroupId;
  647. Fields |= THREAD_IDENTITY_FIELD_REAL_GROUP_ID |
  648. THREAD_IDENTITY_FIELD_EFFECTIVE_GROUP_ID;
  649. }
  650. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  651. if (!KSUCCESS(Status)) {
  652. ClThreadIdentityValid = FALSE;
  653. errno = ClConvertKstatusToErrorNumber(Status);
  654. return -1;
  655. }
  656. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  657. return 0;
  658. }
  659. LIBC_API
  660. int
  661. setresuid (
  662. uid_t RealUserId,
  663. uid_t EffectiveUserId,
  664. uid_t SavedUserId
  665. )
  666. /*++
  667. Routine Description:
  668. This routine sets the real, effective, and saved user IDs of the calling
  669. thread. A unprivileged process may set each one of these to one of the
  670. current real, effective, or saved user ID. A process with the setuid
  671. permission may set these to any values.
  672. Arguments:
  673. RealUserId - Supplies the real user ID to set, or -1 to leave the value
  674. unchanged.
  675. EffectiveUserId - Supplies the effective user ID to set, or -1 to leave the
  676. value unchanged.
  677. SavedUserId - Supplies the saved user ID to set, or -1 to leave the value
  678. unchanged.
  679. Return Value:
  680. 0 on success.
  681. -1 on failure, and errno will be set to contain more information. This may
  682. fail even for root, so the return value must always be checked.
  683. --*/
  684. {
  685. ULONG Fields;
  686. KSTATUS Status;
  687. Fields = 0;
  688. if (RealUserId != (uid_t)-1) {
  689. ClThreadIdentity.RealUserId = RealUserId;
  690. Fields |= THREAD_IDENTITY_FIELD_REAL_USER_ID;
  691. }
  692. if (EffectiveUserId != (uid_t)-1) {
  693. ClThreadIdentity.EffectiveUserId = EffectiveUserId;
  694. Fields |= THREAD_IDENTITY_FIELD_EFFECTIVE_USER_ID;
  695. }
  696. if (SavedUserId != (uid_t)-1) {
  697. ClThreadIdentity.SavedUserId = SavedUserId;
  698. Fields |= THREAD_IDENTITY_FIELD_SAVED_USER_ID;
  699. }
  700. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  701. if (!KSUCCESS(Status)) {
  702. ClThreadIdentityValid = FALSE;
  703. errno = ClConvertKstatusToErrorNumber(Status);
  704. return -1;
  705. }
  706. ClThreadIdentityValid = TRUE;
  707. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  708. return 0;
  709. }
  710. LIBC_API
  711. int
  712. setresgid (
  713. gid_t RealGroupId,
  714. gid_t EffectiveGroupId,
  715. gid_t SavedGroupId
  716. )
  717. /*++
  718. Routine Description:
  719. This routine sets the real, effective, and saved group IDs of the calling
  720. thread. A unprivileged process may set each one of these to one of the
  721. current real, effective, or saved group ID. A process with the setuid
  722. permission may set these to any values.
  723. Arguments:
  724. RealGroupId - Supplies the real group ID to set, or -1 to leave the value
  725. unchanged.
  726. EffectiveGroupId - Supplies the effective group ID to set, or -1 to leave
  727. the value unchanged.
  728. SavedGroupId - Supplies the saved group ID to set, or -1 to leave the value
  729. unchanged.
  730. Return Value:
  731. 0 on success.
  732. -1 on failure, and errno will be set to contain more information. This may
  733. fail even for root, so the return value must always be checked.
  734. --*/
  735. {
  736. ULONG Fields;
  737. KSTATUS Status;
  738. Fields = 0;
  739. if (RealGroupId != (gid_t)-1) {
  740. ClThreadIdentity.RealGroupId = RealGroupId;
  741. Fields |= THREAD_IDENTITY_FIELD_REAL_GROUP_ID;
  742. }
  743. if (EffectiveGroupId != (gid_t)-1) {
  744. ClThreadIdentity.EffectiveGroupId = EffectiveGroupId;
  745. Fields |= THREAD_IDENTITY_FIELD_EFFECTIVE_GROUP_ID;
  746. }
  747. if (SavedGroupId != (gid_t)-1) {
  748. ClThreadIdentity.SavedGroupId = SavedGroupId;
  749. Fields |= THREAD_IDENTITY_FIELD_SAVED_GROUP_ID;
  750. }
  751. Status = OsSetThreadIdentity(Fields, &ClThreadIdentity);
  752. if (!KSUCCESS(Status)) {
  753. ClThreadIdentityValid = FALSE;
  754. errno = ClConvertKstatusToErrorNumber(Status);
  755. return -1;
  756. }
  757. ClThreadIdentityValid = TRUE;
  758. ClpSetThreadIdentityOnAllThreads(Fields, &ClThreadIdentity);
  759. return 0;
  760. }
  761. LIBC_API
  762. int
  763. getgroups (
  764. int ElementCount,
  765. gid_t GroupList[]
  766. )
  767. /*++
  768. Routine Description:
  769. This routine returns the array of supplementary groups that the current
  770. user belongs to.
  771. Arguments:
  772. ElementCount - Supplies the size (in elements) of the supplied group list
  773. buffer.
  774. GroupList - Supplies a buffer where the user's supplementary groups will
  775. be returned.
  776. Return Value:
  777. Returns the number of supplementary groups that the current user belongs to.
  778. The full count is returned even if the element count is less than that so
  779. that the caller can regroup (get it) and try again if the buffer allocated
  780. was too small.
  781. -1 on failure, and errno will be set to contain more information.
  782. --*/
  783. {
  784. UINTN Count;
  785. KSTATUS Status;
  786. Count = ElementCount;
  787. Status = OsSetSupplementaryGroups(FALSE, (PGROUP_ID)GroupList, &Count);
  788. if ((KSUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL)) {
  789. return Count;
  790. }
  791. errno = ClConvertKstatusToErrorNumber(Status);
  792. return -1;
  793. }
  794. LIBC_API
  795. int
  796. setgroups (
  797. size_t ElementCount,
  798. const gid_t *GroupList
  799. )
  800. /*++
  801. Routine Description:
  802. This routine sets the supplementary group membership of the calling
  803. process. The caller must have sufficient privileges to set supplementary
  804. group IDs.
  805. Arguments:
  806. ElementCount - Supplies the size (in elements) of the supplied group list
  807. buffer.
  808. GroupList - Supplies an array of supplementary group IDs.
  809. Return Value:
  810. 0 on success.
  811. -1 on failure, and errno will be set to contain more information.
  812. --*/
  813. {
  814. UINTN Count;
  815. KSTATUS Status;
  816. Count = ElementCount;
  817. Status = OsSetSupplementaryGroups(TRUE, (PGROUP_ID)GroupList, &Count);
  818. if (!KSUCCESS(Status)) {
  819. errno = ClConvertKstatusToErrorNumber(Status);
  820. return -1;
  821. }
  822. ClpSetSupplementaryGroupsOnAllThreads((PGROUP_ID)GroupList, Count);
  823. return 0;
  824. }
  825. LIBC_API
  826. int
  827. nice (
  828. int Increment
  829. )
  830. /*++
  831. Routine Description:
  832. This routine adds the given value to the current process' nice value. A
  833. process' nice value is a non-negative number for which a more positive
  834. value results in less favorable scheduling. Valid nice values are between
  835. 0 and 2 * NZERO - 1.
  836. Arguments:
  837. Increment - Supplies the increment to add to the current nice value.
  838. Return Value:
  839. Returns the new nice value minus NZERO. Note that this can result in a
  840. successful return value of -1. Callers checking for errors should set
  841. errno to 0 before calling this function, then check errno after.
  842. -1 on failure, and errno will be set to indicate more information. This may
  843. fail with EPERM if the increment is negative and the caller does not have
  844. appropriate privileges.
  845. --*/
  846. {
  847. //
  848. // TODO: Implement nice.
  849. //
  850. return 0;
  851. }
  852. //
  853. // --------------------------------------------------------- Internal Functions
  854. //