[starnix] Very partially implement prlimit

This only re-implements in prlimit the few resources that were already
in getrlimit. This also implements setrlimit and refactor getrlimit by
always delegating to prlimit

Change-Id: Ib6e0191687af18e731be570266f15cd5d08daff6
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/693084
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Reviewed-by: Adam Barth <abarth@google.com>
Fuchsia-Auto-Submit: Benjamin Lerman <qsr@google.com>
diff --git a/src/proc/bin/starnix/syscalls/table.rs b/src/proc/bin/starnix/syscalls/table.rs
index 2d820dab..96c8cd5 100644
--- a/src/proc/bin/starnix/syscalls/table.rs
+++ b/src/proc/bin/starnix/syscalls/table.rs
@@ -158,6 +158,7 @@
         pread64[4],
         process_vm_readv[6],
         pselect6[6],
+        prlimit64[4],
         pwrite64[4],
         read[3],
         readlink[3],
@@ -184,7 +185,6 @@
         sendmmsg[4],
         sendmsg[3],
         sendto[6],
-        set_tid_address[1],
         setgid[1],
         setgroups[2],
         setitimer[3],
@@ -192,8 +192,10 @@
         setpriority[3],
         setresgid[3],
         setresuid[3],
+        setrlimit[2],
         setsid[0],
         setsockopt[5],
+        set_tid_address[1],
         setuid[1],
         setxattr[5],
         shutdown[2],
diff --git a/src/proc/bin/starnix/task/syscalls.rs b/src/proc/bin/starnix/task/syscalls.rs
index 48b76e9..473d3837 100644
--- a/src/proc/bin/starnix/task/syscalls.rs
+++ b/src/proc/bin/starnix/task/syscalls.rs
@@ -514,24 +514,52 @@
     resource: u32,
     user_rlimit: UserRef<rlimit>,
 ) -> Result<(), Errno> {
-    let limit = match resource {
-        resource if resource == RLIMIT_NOFILE => {
-            Ok(rlimit { rlim_cur: RLIMIT_NOFILE_MAX, rlim_max: RLIMIT_NOFILE_MAX })
-        }
-        resource if resource == RLIMIT_STACK => {
-            // The stack size is fixed at the moment, but
-            // if MAP_GROWSDOWN is implemented this should
-            // report the limit that it can be grown.
-            let mm_state = current_task.mm.state.read();
-            let stack_size = mm_state.stack_size as u64;
-            Ok(rlimit { rlim_cur: stack_size, rlim_max: stack_size })
-        }
-        _ => {
-            not_implemented!("getrlimit: {:?}", resource);
-            error!(ENOSYS)
-        }
-    }?;
-    current_task.mm.write_object(user_rlimit, &limit)?;
+    sys_prlimit64(current_task, 0, resource, Default::default(), user_rlimit)
+}
+
+pub fn sys_setrlimit(
+    current_task: &CurrentTask,
+    resource: u32,
+    user_rlimit: UserRef<rlimit>,
+) -> Result<(), Errno> {
+    sys_prlimit64(current_task, 0, resource, user_rlimit, Default::default())
+}
+
+pub fn sys_prlimit64(
+    current_task: &CurrentTask,
+    pid: pid_t,
+    resource: u32,
+    new_limit: UserRef<rlimit>,
+    old_limit: UserRef<rlimit>,
+) -> Result<(), Errno> {
+    if pid != 0 {
+        not_implemented!("prlimit64 with non 0 pid");
+        return error!(ENOSYS);
+    }
+    if !new_limit.is_null() {
+        not_implemented!("prlimit64 to edit limits");
+        return error!(ENOSYS);
+    }
+    if !old_limit.is_null() {
+        let limit = match resource {
+            resource if resource == RLIMIT_NOFILE => {
+                Ok(rlimit { rlim_cur: RLIMIT_NOFILE_MAX, rlim_max: RLIMIT_NOFILE_MAX })
+            }
+            resource if resource == RLIMIT_STACK => {
+                // The stack size is fixed at the moment, but
+                // if MAP_GROWSDOWN is implemented this should
+                // report the limit that it can be grown.
+                let mm_state = current_task.mm.state.read();
+                let stack_size = mm_state.stack_size as u64;
+                Ok(rlimit { rlim_cur: stack_size, rlim_max: stack_size })
+            }
+            _ => {
+                not_implemented!("getrlimit: {:?}", resource);
+                error!(ENOSYS)
+            }
+        }?;
+        current_task.mm.write_object(old_limit, &limit)?;
+    }
     Ok(())
 }