Fix getpeerucred and ucred_get
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / ucred.c
index bfc15d4..5da3485 100644 (file)
 
 #include <inline-syscall.h>
 #include <unistd.h>
-#include <ucred.h>
-#include <errno.h>
 #include <ucredP.h>
+#include <auditP.h>
 #include <priv.h>
+#include <procfs.h>
+#include <errno.h>
 #include <assert.h>
 
 DECLARE_INLINE_SYSCALL (int, getpeerucred, int fd, ucred_t *ucred);
 DECLARE_INLINE_SYSCALL (int, ucred_get, pid_t pid, ucred_t *ucred);
-DECLARE_INLINE_SYSCALL (int, syslabeling, void);
 
 /* Docs: http://docs.sun.com/app/docs/doc/816-5168/ucred-get-3c?a=view
          http://docs.sun.com/app/docs/doc/816-5168/getpeerucred-3c?l=ru&a=view */
 
-ucred_t *ucred_get (pid_t pid)
+
+ucred_t *_ucred_alloc (void)
 {
   size_t uc_size = ucred_size ();
   ucred_t *uc = malloc (uc_size);
+  if (uc)
+    uc->uc_size = uc_size;
+  return uc;
+}
+
+
+ucred_t *ucred_get (pid_t pid)
+{
+  ucred_t *uc = _ucred_alloc ();
   if (!uc)
     return NULL;
-  uc->uc_size = uc_size;
 
-  INLINE_SYSCALL (ucred_get, 2, pid, uc);
+  int res = INLINE_SYSCALL (ucred_get, 2, pid, uc);
+  if (res != 0)
+    return NULL;
 
   return uc;
 }
@@ -52,30 +63,83 @@ void ucred_free (ucred_t *uc)
 }
 
 
-#define MAKE_PRCRED_T_CALL(field, type)                                     \
-  type ucred_get##field (const ucred_t *uc)                                 \
-  {                                                                         \
-    if (uc->uc_credoff == 0)                                                \
-      {                                                                     \
-        __set_errno(EINVAL);                                                \
-        return (type)-1;                                                    \
-      }                                                                     \
-    return (type)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_##field;   \
-   }
+uid_t ucred_geteuid (const ucred_t *uc)
+{
+  if (uc->uc_credoff == 0)
+    {
+      __set_errno (EINVAL);
+      return (uid_t)-1;
+    }
+
+  return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_euid;
+}
+
+
+uid_t ucred_getruid (const ucred_t *uc)
+{
+  if (uc->uc_credoff == 0)
+    {
+      __set_errno (EINVAL);
+      return (uid_t)-1;
+    }
 
-MAKE_PRCRED_T_CALL (euid, uid_t)
-MAKE_PRCRED_T_CALL (ruid, uid_t)
-MAKE_PRCRED_T_CALL (suid, uid_t)
-MAKE_PRCRED_T_CALL (egid, gid_t)
-MAKE_PRCRED_T_CALL (rgid, gid_t)
-MAKE_PRCRED_T_CALL (sgid, gid_t)
+  return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_ruid;
+}
+
+
+uid_t ucred_getsuid (const ucred_t *uc)
+{
+  if (uc->uc_credoff == 0)
+    {
+      __set_errno (EINVAL);
+      return (uid_t)-1;
+    }
+
+  return (uid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_suid;
+}
+
+
+gid_t ucred_getegid (const ucred_t *uc)
+{
+  if (uc->uc_credoff == 0)
+    {
+      __set_errno (EINVAL);
+      return (gid_t)-1;
+    }
+
+  return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_egid;
+}
+
+
+gid_t ucred_getrgid (const ucred_t *uc)
+{
+  if (uc->uc_credoff == 0)
+    {
+      __set_errno (EINVAL);
+      return (gid_t)-1;
+    }
+
+  return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_rgid;
+}
+
+
+gid_t ucred_getsgid (const ucred_t *uc)
+{
+  if (uc->uc_credoff == 0)
+    {
+      __set_errno(EINVAL);                                                \
+      return (gid_t)-1;                                                    \
+    }
+
+  return (gid_t)((prcred_t *)((char *)uc + uc->uc_credoff))->pr_sgid;
+}
 
 
 int ucred_getgroups (const ucred_t *uc, const gid_t **groups)
 {
   if (uc->uc_credoff == 0 || groups == NULL)
     {
-      __set_errno(EINVAL);
+      __set_errno (EINVAL);
       return -1;
     }
 
@@ -91,14 +155,23 @@ int ucred_getgroups (const ucred_t *uc, const gid_t **groups)
 }
 
 
-#if 0
 const priv_set_t *ucred_getprivset (const ucred_t *uc, const char *set)
 {
-  // TODO
-  __set_errno (ENOSYS);
-  return NULL;
+  /* Get prpriv_t.  */
+  if (uc->uc_privoff == 0)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+  prpriv_t * pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
+
+  /* Get priv set number.  */
+  int setnum = priv_getsetbyname (set);
+  if (setnum == -1)
+    return NULL;
+
+  return (priv_set_t *)&pr->pr_sets[setnum * pr->pr_setsize];
 }
-#endif
 
 
 pid_t ucred_getpid (const ucred_t *uc)
@@ -128,20 +201,40 @@ zoneid_t ucred_getzoneid (const ucred_t *uc)
 }
 
 
-#if 0
 unsigned int ucred_getpflags (const ucred_t *uc, unsigned int flags)
 {
-  // TODO
-  __set_errno (ENOSYS);
-  return -1;
+  /* Get prpriv_t.  */
+  if (uc->uc_privoff == 0)
+    {
+      __set_errno (EINVAL);
+      return (unsigned int)-1;
+    }
+  prpriv_t *pr = (prpriv_t *)((char *)uc + uc->uc_privoff);
+
+  /* Iterate over all priv_info_t's. Note that the first priv_info_t follows
+     the list of priv sets.  */
+  priv_info_t * pi = (priv_info_t *)&pr->pr_sets[pr->pr_nsets * pr->pr_setsize];
+  uint32_t left = pr->pr_infosize;
+  while (left)
+    {
+      if (pi->priv_info_type == PRIV_INFO_FLAGS)
+        return ((priv_info_uint_t *)pi)->val & flags;
+
+      left -= pi->priv_info_size;
+      pi = (priv_info_t *)((char *)pi + pi->priv_info_size);
+    }
+
+  /* We didn't find PRIV_INFO_FLAGS.  */
+  __set_errno (EINVAL);
+  return (unsigned int)-1;
 }
-#endif
 
 
 m_label_t *ucred_getlabel (const ucred_t *uc)
 {
-  int syslabeling = INLINE_SYSCALL (syslabeling, 0);
-  if (!syslabeling || uc->uc_labeloff == 0)
+  extern int is_system_labeled (void);
+
+  if (!is_system_labeled () || uc->uc_labeloff == 0)
     {
       __set_errno (EINVAL);
       return NULL;
@@ -151,18 +244,64 @@ m_label_t *ucred_getlabel (const ucred_t *uc)
 }
 
 
-size_t ucred_size (void)
+au_id_t ucred_getauid (const ucred_t *uc)
+{
+  if (uc->uc_audoff == 0)
+    return AU_NOAUDITID;
+  const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+      ((char *)uc + uc->uc_audoff);
+
+  return info->ai_auid;
+}
+
+
+au_asid_t ucred_getasid (const ucred_t *uc)
+{
+  if (uc->uc_audoff == 0)
+    return (au_asid_t)-1;
+  const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+      ((char *)uc + uc->uc_audoff);
+
+  return info->ai_asid;
+}
+
+
+const au_tid64_addr_t * ucred_getatid (const ucred_t *uc)
 {
-    const priv_impl_info_t *info = getprivimplinfo ();
+  if (uc->uc_audoff == 0)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+  const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+      ((char *)uc + uc->uc_audoff);
+
+  return &info->ai_termid;
+}
 
-    /* ucred_size cannot fail.  */
-    assert (info);
 
-    /* XXX: We shouldn't use AUDITINFO64_ADDR_T_SIZE and BSLABEL_T_SIZE.  */
-    return sizeof(ucred_t) + sizeof(prcred_t) + sizeof(prpriv_t) +
-        ((int)sysconf (_SC_NGROUPS_MAX) - 1) * sizeof(gid_t) +
-        sizeof(priv_chunk_t) * (info->priv_setsize * info->priv_nsets - 1) +
-        info->priv_infosize + AUDITINFO64_ADDR_T_SIZE + BSLABEL_T_SIZE;
+const au_mask_t * ucred_getamask (const ucred_t *uc)
+{
+  if (uc->uc_audoff == 0)
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+  const auditinfo64_addr_t *info = (auditinfo64_addr_t *)
+      ((char *)uc + uc->uc_audoff);
+
+  return &info->ai_mask;
+}
+
+
+size_t ucred_size (void)
+{
+  const priv_impl_info_t *info = getprivimplinfo ();
+
+  return sizeof (ucred_t) + sizeof (prcred_t) + sizeof (prpriv_t) +
+    ((int)sysconf (_SC_NGROUPS_MAX) - 1) * sizeof (gid_t) +
+    sizeof (priv_chunk_t) * (info->priv_setsize * info->priv_nsets - 1) +
+    info->priv_infosize + sizeof (auditinfo64_addr_t) + BSLABEL_T_SIZE;
 }
 
 
@@ -171,21 +310,19 @@ int getpeerucred (int fd, ucred_t **ucred)
   ucred_t *uc = *ucred;
 
   /* alloc ucred if needed */
-  if(*ucred == NULL)
+  if (*ucred == NULL)
     {
-      size_t uc_size = ucred_size ();
-      ucred_t *uc = malloc (uc_size);
+      uc = _ucred_alloc ();
       if (!uc)
         return -1;
-      uc->uc_size = uc_size;
       *ucred = uc;
     }
 
-  int result = INLINE_SYSCALL (getpeerucred, 2, fd, uc);
-  if (result == -1 && *ucred == NULL)
+  int res = INLINE_SYSCALL (getpeerucred, 2, fd, uc);
+  if (res == -1 && *ucred == NULL)
       free (uc);
-  else if (result == 0 && *ucred == NULL)
+  else if (res == 0 && *ucred == NULL)
       *ucred = uc;
 
-  return result;
+  return res;
 }