@@ -10,7 +10,7 @@ use crate::{
1010 to_user,
1111 } ,
1212 sched:: Scheduler ,
13- uapi:: { self , limits:: PATH_MAX , pid_t, uid_t} ,
13+ uapi:: { self , gid_t , limits:: PATH_MAX , pid_t, uid_t} ,
1414 vfs:: { File , file:: OpenFlags , inode:: Mode } ,
1515 wrap_syscall,
1616} ;
@@ -76,14 +76,83 @@ pub fn getresuid(ruid: VirtAddr, euid: VirtAddr, suid: VirtAddr) -> EResult<()>
7676 Ok ( ( ) )
7777}
7878
79+ #[ wrap_syscall]
80+ pub fn setuid ( uid : uid_t ) -> EResult < ( ) > {
81+ let proc = Scheduler :: get_current ( ) . get_process ( ) ;
82+ let mut ident = proc. identity . lock ( ) ;
83+ if ident. is_effective_superuser ( ) {
84+ ident. user_id = uid;
85+ ident. effective_user_id = uid;
86+ ident. set_user_id = uid;
87+ Ok ( ( ) )
88+ } else if uid == ident. user_id || uid == ident. effective_user_id || uid == ident. set_user_id {
89+ ident. effective_user_id = uid;
90+ Ok ( ( ) )
91+ } else {
92+ Err ( Errno :: EPERM )
93+ }
94+ }
95+
96+ #[ wrap_syscall]
97+ pub fn seteuid ( euid : uid_t ) -> EResult < ( ) > {
98+ let proc = Scheduler :: get_current ( ) . get_process ( ) ;
99+ let mut ident = proc. identity . lock ( ) ;
100+ if ident. is_effective_superuser ( )
101+ || euid == ident. user_id
102+ || euid == ident. effective_user_id
103+ || euid == ident. set_user_id
104+ {
105+ ident. effective_user_id = euid;
106+ Ok ( ( ) )
107+ } else {
108+ Err ( Errno :: EPERM )
109+ }
110+ }
111+
112+ #[ wrap_syscall]
113+ pub fn setresuid ( ruid : uid_t , euid : uid_t , suid : uid_t ) -> EResult < ( ) > {
114+ setresuid_inner ( ruid, euid, suid)
115+ }
116+
117+ #[ wrap_syscall]
118+ pub fn setreuid ( ruid : uid_t , euid : uid_t ) -> EResult < ( ) > {
119+ setresuid_inner ( ruid, euid, uid_t:: MAX )
120+ }
121+
122+ fn setresuid_inner ( ruid : uid_t , euid : uid_t , suid : uid_t ) -> EResult < ( ) > {
123+ let proc = Scheduler :: get_current ( ) . get_process ( ) ;
124+ let mut ident = proc. identity . lock ( ) ;
125+ if !ident. is_effective_superuser ( ) {
126+ for uid in [ ruid, euid, suid] {
127+ if uid != uid_t:: MAX
128+ && uid != ident. user_id
129+ && uid != ident. effective_user_id
130+ && uid != ident. set_user_id
131+ {
132+ return Err ( Errno :: EPERM ) ;
133+ }
134+ }
135+ }
136+ if ruid != uid_t:: MAX {
137+ ident. user_id = ruid;
138+ }
139+ if euid != uid_t:: MAX {
140+ ident. effective_user_id = euid;
141+ }
142+ if suid != uid_t:: MAX {
143+ ident. set_user_id = suid;
144+ }
145+ Ok ( ( ) )
146+ }
147+
79148#[ wrap_syscall]
80149pub fn getresgid ( rgid : VirtAddr , egid : VirtAddr , sgid : VirtAddr ) -> EResult < ( ) > {
81150 let proc = Scheduler :: get_current ( ) . get_process ( ) ;
82151 let ident = proc. identity . lock ( ) ;
83152
84- let mut rgid_ptr = UserPtr :: < uid_t > :: new ( rgid) ;
85- let mut egid_ptr = UserPtr :: < uid_t > :: new ( egid) ;
86- let mut sgid_ptr = UserPtr :: < uid_t > :: new ( sgid) ;
153+ let mut rgid_ptr = UserPtr :: < gid_t > :: new ( rgid) ;
154+ let mut egid_ptr = UserPtr :: < gid_t > :: new ( egid) ;
155+ let mut sgid_ptr = UserPtr :: < gid_t > :: new ( sgid) ;
87156
88157 rgid_ptr. write ( ident. group_id ) . ok_or ( Errno :: EFAULT ) ?;
89158 egid_ptr
@@ -94,6 +163,76 @@ pub fn getresgid(rgid: VirtAddr, egid: VirtAddr, sgid: VirtAddr) -> EResult<()>
94163 Ok ( ( ) )
95164}
96165
166+ #[ wrap_syscall]
167+ pub fn setgid ( gid : gid_t ) -> EResult < ( ) > {
168+ let proc = Scheduler :: get_current ( ) . get_process ( ) ;
169+ let mut ident = proc. identity . lock ( ) ;
170+ if ident. is_effective_superuser ( ) {
171+ ident. group_id = gid;
172+ ident. effective_group_id = gid;
173+ ident. set_group_id = gid;
174+ Ok ( ( ) )
175+ } else if gid == ident. group_id || gid == ident. effective_group_id || gid == ident. set_group_id
176+ {
177+ ident. effective_group_id = gid;
178+ Ok ( ( ) )
179+ } else {
180+ Err ( Errno :: EPERM )
181+ }
182+ }
183+
184+ #[ wrap_syscall]
185+ pub fn setegid ( egid : gid_t ) -> EResult < ( ) > {
186+ let proc = Scheduler :: get_current ( ) . get_process ( ) ;
187+ let mut ident = proc. identity . lock ( ) ;
188+ if ident. is_effective_superuser ( )
189+ || egid == ident. group_id
190+ || egid == ident. effective_group_id
191+ || egid == ident. set_group_id
192+ {
193+ ident. effective_group_id = egid;
194+ Ok ( ( ) )
195+ } else {
196+ Err ( Errno :: EPERM )
197+ }
198+ }
199+
200+ #[ wrap_syscall]
201+ pub fn setresgid ( rgid : gid_t , egid : gid_t , sgid : gid_t ) -> EResult < ( ) > {
202+ setresgid_inner ( rgid, egid, sgid)
203+ }
204+
205+ #[ wrap_syscall]
206+ pub fn setregid ( rgid : gid_t , egid : gid_t ) -> EResult < ( ) > {
207+ setresgid_inner ( rgid, egid, gid_t:: MAX )
208+ }
209+
210+ fn setresgid_inner ( rgid : gid_t , egid : gid_t , sgid : gid_t ) -> EResult < ( ) > {
211+ let proc = Scheduler :: get_current ( ) . get_process ( ) ;
212+ let mut ident = proc. identity . lock ( ) ;
213+ if !ident. is_effective_superuser ( ) {
214+ for gid in [ rgid, egid, sgid] {
215+ if gid != gid_t:: MAX
216+ && gid != ident. group_id
217+ && gid != ident. effective_group_id
218+ && gid != ident. set_group_id
219+ {
220+ return Err ( Errno :: EPERM ) ;
221+ }
222+ }
223+ }
224+ if rgid != gid_t:: MAX {
225+ ident. group_id = rgid;
226+ }
227+ if egid != gid_t:: MAX {
228+ ident. effective_group_id = egid;
229+ }
230+ if sgid != gid_t:: MAX {
231+ ident. set_group_id = sgid;
232+ }
233+ Ok ( ( ) )
234+ }
235+
97236#[ wrap_syscall]
98237pub fn getpgid ( pid : pid_t ) -> EResult < pid_t > {
99238 let proc = if pid == 0 {
@@ -344,6 +483,10 @@ pub fn waitpid(pid: pid_t, stat_loc: VirtAddr, options: i32) -> EResult<pid_t> {
344483 return Ok ( 0 ) ;
345484 }
346485
486+ if Scheduler :: get_current ( ) . has_pending_signals ( ) {
487+ return Err ( Errno :: EINTR ) ;
488+ }
489+
347490 drop ( children) ;
348491 guard. wait ( ) ;
349492
@@ -358,6 +501,7 @@ pub fn waitpid(pid: pid_t, stat_loc: VirtAddr, options: i32) -> EResult<pid_t> {
358501 }
359502 let state = child. status . lock ( ) ;
360503 matches ! ( * state, ProcessState :: Exited ( _) )
504+ || matches ! ( * state, ProcessState :: Signaled ( _) )
361505 || ( ( options & uapi:: wait:: WUNTRACED ) != 0
362506 && child. stop_unwaited . load ( Ordering :: Acquire ) )
363507 || ( ( options & uapi:: wait:: WCONTINUED ) != 0
0 commit comments