afs: Properly type afs_osi_suser cred arg
[openafs.git] / src / afs / afs_pioctl.c
index 4efcd51..eee4d88 100644 (file)
@@ -55,8 +55,9 @@ struct afs_pdata {
 static_inline int
 afs_pd_alloc(struct afs_pdata *apd, size_t size)
 {
-
-    if (size > AFS_LRALLOCSIZ)
+    /* Ensure that we give caller at least one trailing guard byte
+     * for the NUL terminator. */
+    if (size >= AFS_LRALLOCSIZ)
        apd->ptr = osi_Alloc(size + 1);
     else
        apd->ptr = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
@@ -64,11 +65,13 @@ afs_pd_alloc(struct afs_pdata *apd, size_t size)
     if (apd->ptr == NULL)
        return ENOMEM;
 
-    if (size > AFS_LRALLOCSIZ)
+    /* Clear it all now, including the guard byte. */
+    if (size >= AFS_LRALLOCSIZ)
        memset(apd->ptr, 0, size + 1);
     else
        memset(apd->ptr, 0, AFS_LRALLOCSIZ);
 
+    /* Don't tell the caller about the guard byte. */
     apd->remaining = size;
 
     return 0;
@@ -80,7 +83,7 @@ afs_pd_free(struct afs_pdata *apd)
     if (apd->ptr == NULL)
        return;
 
-    if (apd->remaining > AFS_LRALLOCSIZ)
+    if (apd->remaining >= AFS_LRALLOCSIZ)
        osi_Free(apd->ptr, apd->remaining + 1);
     else
        osi_FreeLargeSpace(apd->ptr);
@@ -825,7 +828,7 @@ afs_xioctl(afs_proc_t *p, const struct ioctl_args *uap, register_t *retval)
 #if defined(AFS_NBSD50_ENV)
     if ((fd = fd_getfile(SCARG(uap, fd))) == NULL)
        return (EBADF);
-#elif defined(AFS_FBSD100_ENV)
+#elif defined(AFS_FBSD_ENV)
     if ((uap->fd >= fdp->fd_nfiles)
        || ((fd = fdp->fd_ofiles[uap->fd].fde_file) == NULL))
        return EBADF;
@@ -884,11 +887,7 @@ afs_xioctl(afs_proc_t *p, const struct ioctl_args *uap, register_t *retval)
 
     if (!ioctlDone) {
 # if defined(AFS_FBSD_ENV)
-#  if (__FreeBSD_version >= 900044)
        return sys_ioctl(td, uap);
-#  else
-       return ioctl(td, uap);
-#  endif
 # elif defined(AFS_OBSD_ENV)
        code = sys_ioctl(p, uap, retval);
 # elif defined(AFS_NBSD_ENV)
@@ -1255,10 +1254,10 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
        dput(dp);
        AFS_GLOCK();
 #else
-#if defined(AFS_FBSD80_ENV)
+#if defined(AFS_FBSD_ENV)
     if (VOP_ISLOCKED(vp))
        VOP_UNLOCK(vp, 0);
-#endif /* AFS_FBSD80_ENV */
+#endif /* AFS_FBSD_ENV */
        AFS_RELE(vp);           /* put vnode back */
 #endif
     }
@@ -1475,15 +1474,10 @@ DECL_PIOCTL(PSetAcl)
              SHARED_LOCK, NULL));
 
     /* now we've forgotten all of the access info */
-    ObtainWriteLock(&afs_xcbhash, 455);
-    avc->callback = 0;
-    afs_DequeueCallback(avc);
-    avc->f.states &= ~(CStatd | CUnique);
-    ReleaseWriteLock(&afs_xcbhash);
-    if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-       osi_dnlc_purgedp(avc);
+    afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
 
     /* SXW - Should we flush metadata here? */
+
     return code;
 }
 
@@ -2071,6 +2065,7 @@ DECL_PIOCTL(PSetVolumeStatus)
     AFS_STATCNT(PSetVolumeStatus);
     if (!avc)
        return EINVAL;
+    memset(&storeStat, 0, sizeof(storeStat));
 
     tvp = afs_GetVolume(&avc->f.fid, areq, READ_LOCK);
     if (tvp) {
@@ -2227,9 +2222,9 @@ DECL_PIOCTL(PNewStatMount)
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
-       tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
+       tvc = afs_LookupVCache(&tfid, areq, avc, bufp);
     } else {
-       tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+       tvc = afs_GetVCache(&tfid, areq);
     }
     if (!tvc) {
        code = EIO;
@@ -2275,6 +2270,9 @@ getNthCell(afs_int32 uid, afs_int32 iterator) {
     int i;
     struct unixuser *tu = NULL;
 
+    if (iterator > afs_cellindex)
+       return NULL;            /* no point in looking */
+
     i = UHash(uid);
     ObtainReadLock(&afs_xuser);
     for (tu = afs_users[i]; tu; tu = tu->next) {
@@ -2920,7 +2918,7 @@ DECL_PIOCTL(PGetCacheSize)
     afs_int32 results[MAXGCSTATS];
     afs_int32 flags;
     struct dcache * tdc;
-    int i, size;
+    int i;
 
     AFS_STATCNT(PGetCacheSize);
 
@@ -2952,9 +2950,10 @@ DECL_PIOCTL(PGetCacheSize)
 
            tdc = afs_indexTable[i];
            if (tdc){
+               afs_size_t size = tdc->validPos;
+
                results[9]++;
-               size = tdc->validPos;
-               if ( 0 < size && size < (1<<12) ) results[10]++;
+               if ( 0 <= size && size < (1<<12) ) results[10]++;
                else if (size < (1<<14) ) results[11]++;
                else if (size < (1<<16) ) results[12]++;
                else if (size < (1<<18) ) results[13]++;
@@ -3018,13 +3017,7 @@ DECL_PIOCTL(PRemoveCallBack)
                 (tc, rxconn, code, &avc->f.fid, areq,
                  AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS, SHARED_LOCK, NULL));
 
-       ObtainWriteLock(&afs_xcbhash, 457);
-       afs_DequeueCallback(avc);
-       avc->callback = 0;
-       avc->f.states &= ~(CStatd | CUnique);
-       ReleaseWriteLock(&afs_xcbhash);
-       if (avc->f.fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-           osi_dnlc_purgedp(avc);
+       afs_StaleVCacheFlags(avc, AFS_STALEVC_CLEARCB, CUnique);
     }
     ReleaseWriteLock(&avc->lock);
     return 0;
@@ -3078,7 +3071,7 @@ DECL_PIOCTL(PNewCell)
      * This whole logic is bogus, because it relies on the newer command
      * sending its 12th address as 0.
      */
-    if ((afs_pd_remaining(ain) < AFS_MAXCELLHOSTS +3) * sizeof(afs_int32))
+    if (afs_pd_remaining(ain) < (AFS_MAXCELLHOSTS + 3) * sizeof(afs_int32))
        return EINVAL;
 
     newcell = afs_pd_where(ain) + (AFS_MAXCELLHOSTS + 3) * sizeof(afs_int32);
@@ -3290,9 +3283,9 @@ DECL_PIOCTL(PRemoveMount)
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
-       tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
+       tvc = afs_LookupVCache(&tfid, areq, avc, bufp);
     } else {
-       tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+       tvc = afs_GetVCache(&tfid, areq);
     }
     if (!tvc) {
        code = EIO;
@@ -3450,7 +3443,7 @@ DECL_PIOCTL(PSetCellStatus)
     return 0;
 }
 
-static void
+static int
 FlushVolumeData(struct VenusFid *afid, afs_ucred_t * acred)
 {
     afs_int32 i;
@@ -3461,6 +3454,7 @@ FlushVolumeData(struct VenusFid *afid, afs_ucred_t * acred)
     afs_int32 cell = 0;
     afs_int32 volume = 0;
     struct afs_q *tq, *uq;
+    int code = 0;
 #ifdef AFS_DARWIN80_ENV
     vnode_t vp;
 #endif
@@ -3529,7 +3523,8 @@ FlushVolumeData(struct VenusFid *afid, afs_ucred_t * acred)
            continue;           /* never had any data */
        tdc = afs_GetValidDSlot(i);
        if (!tdc) {
-           continue;
+            code = EIO;
+            break;
        }
        if (tdc->refCount <= 1) {    /* too high, in use by running sys call */
            ReleaseReadLock(&tdc->tlock);
@@ -3570,6 +3565,7 @@ FlushVolumeData(struct VenusFid *afid, afs_ucred_t * acred)
     /* probably, a user is doing this, probably, because things are screwed up.
      * maybe it's the dnlc's fault? */
     osi_dnlc_purge();
+    return code;
 }
 
 /*!
@@ -3600,8 +3596,7 @@ DECL_PIOCTL(PFlushVolumeData)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    FlushVolumeData(&avc->f.fid, *acred);
-    return 0;
+    return FlushVolumeData(&avc->f.fid, *acred);
 }
 
 /*!
@@ -3631,8 +3626,7 @@ DECL_PIOCTL(PFlushAllVolumeData)
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    FlushVolumeData(NULL, *acred);
-    return 0;
+    return FlushVolumeData(NULL, *acred);
 }
 
 /*!
@@ -4596,7 +4590,7 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
     newcred->cr_groupset.gs_union.un_groups[0] = g0;
     newcred->cr_groupset.gs_union.un_groups[1] = g1;
 #elif defined(AFS_LINUX26_ENV)
-# ifdef AFS_LINUX26_ONEGROUP_ENV
+# ifdef AFS_PAG_ONEGROUP_ENV
     afs_set_cr_group_info(newcred, groups_alloc(1)); /* nothing sets this */
     l = (((g0-0x3f00) & 0x3fff) << 14) | ((g1-0x3f00) & 0x3fff);
     h = ((g0-0x3f00) >> 14);
@@ -4608,9 +4602,14 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
     GROUP_AT(afs_cr_group_info(newcred), 1) = g1;
 # endif
 #elif defined(AFS_SUN510_ENV)
+# ifdef AFS_PAG_ONEGROUP_ENV
+    gids[0] = afs_get_pag_from_groups(g0, g1);
+    crsetgroups(newcred, 1, gids);
+# else
     gids[0] = g0;
     gids[1] = g1;
     crsetgroups(newcred, 2, gids);
+# endif /* !AFS_PAG_ONEGROUP_ENV */
 #else
     newcred->cr_groups[0] = g0;
     newcred->cr_groups[1] = g1;
@@ -4618,7 +4617,7 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
 #ifdef AFS_AIX_ENV
     newcred->cr_ngrps = 2;
 #elif !defined(AFS_LINUX26_ENV) && !defined(AFS_SUN510_ENV)
-# if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_FBSD80_ENV)
+# if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_FBSD_ENV)
     newcred->cr_ngroups = 2;
 # else
     for (i = 2; i < NGROUPS; i++)
@@ -4763,10 +4762,6 @@ DECL_PIOCTL(PSetCPrefs)
 
     if (ainSize < sizeof(struct setspref))
        return EINVAL;
-#if 0                          /* num_servers is unsigned */
-    if (sin->num_servers < 0)
-       return EINVAL;
-#endif
     if (sin->num_servers > AFS_MAX_INTERFACE_ADDR)
        return ENOMEM;
 
@@ -4841,9 +4836,9 @@ DECL_PIOCTL(PFlushMount)
     tfid.Cell = avc->f.fid.Cell;
     tfid.Fid.Volume = avc->f.fid.Fid.Volume;
     if (!tfid.Fid.Unique && (avc->f.states & CForeign)) {
-       tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
+       tvc = afs_LookupVCache(&tfid, areq, avc, bufp);
     } else {
-       tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+       tvc = afs_GetVCache(&tfid, areq);
     }
     if (!tvc) {
        code = EIO;
@@ -4855,13 +4850,10 @@ DECL_PIOCTL(PFlushMount)
        goto out;
     }
     ObtainWriteLock(&tvc->lock, 649);
-    ObtainWriteLock(&afs_xcbhash, 650);
-    afs_DequeueCallback(tvc);
-    tvc->f.states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
-    ReleaseWriteLock(&afs_xcbhash);
+    /* next reference will re-stat cache entry */
+    afs_StaleVCacheFlags(tvc, 0, CDirty);
     /* now find the disk cache entries */
     afs_TryToSmush(tvc, *acred, 1);
-    osi_dnlc_purgedp(tvc);
     if (tvc->linkData && !(tvc->f.states & CCore)) {
        afs_osi_Free(tvc->linkData, strlen(tvc->linkData) + 1);
        tvc->linkData = NULL;
@@ -4982,7 +4974,7 @@ DECL_PIOCTL(PPrefetchFromTape)
     tfid.Fid.Vnode = Fid->Vnode;
     tfid.Fid.Unique = Fid->Unique;
 
-    tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+    tvc = afs_GetVCache(&tfid, areq);
     if (!tvc) {
        afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD, ICL_TYPE_POINTER, tvc,
                   ICL_TYPE_FID, &tfid, ICL_TYPE_FID, &avc->f.fid);
@@ -5053,7 +5045,7 @@ DECL_PIOCTL(PFsCmd)
     tfid.Fid.Vnode = Fid->Vnode;
     tfid.Fid.Unique = Fid->Unique;
 
-    tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
+    tvc = afs_GetVCache(&tfid, areq);
     afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD, ICL_TYPE_POINTER, tvc,
               ICL_TYPE_INT32, Inputs->command, ICL_TYPE_FID, &tfid);
     if (!tvc)
@@ -5153,12 +5145,12 @@ DECL_PIOCTL(PSetCachingThreshold)
 DECL_PIOCTL(PCallBackAddr)
 {
 #ifndef UKERNEL
-    afs_uint32 addr, code;
+    afs_uint32 code;
     int srvAddrCount;
     struct server *ts;
     struct srvAddr *sa;
     struct afs_conn *tc;
-    afs_int32 i, j;
+    afs_int32 i, j, addr;
     struct unixuser *tu;
     struct srvAddr **addrs;
     struct rx_connection *rxconn;
@@ -5167,7 +5159,7 @@ DECL_PIOCTL(PCallBackAddr)
     if (!afs_resourceinit_flag)        /* afs deamons havn't started yet */
        return EIO;             /* Inappropriate ioctl for device */
 
-    if (!afs_osi_suser(acred))
+    if (!afs_osi_suser(*acred))
        return EACCES;
 
     if (afs_pd_getInt(ain, &addr) != 0)
@@ -5244,6 +5236,7 @@ DECL_PIOCTL(PCallBackAddr)
        }
        afs_PutConn(tc, rxconn, SHARED_LOCK);   /* done with it now */
     }                          /* Outer loop over addrs */
+    afs_osi_Free(addrs, srvAddrCount * sizeof(*addrs));
 #endif /* UKERNEL */
     return 0;
 }
@@ -5442,6 +5435,26 @@ out:
     return code;
 }
 
+/*!
+ * VIOC_GETTOK2 (7) - Return a user's nth token, or token for a cell by
+ *                     name.
+ *
+ * \ingroup pioctl
+ *
+ * \param[in] ain      EITHER  a string cellname
+ *                     OR      an integer 'iterator' to specify the nth
+ *                             token.
+ *
+ * \param[out] aout    XDR-encoded tokens from the user's tokenJar
+ *
+ * \retval EINVAL      invalid input (bad integer, or invalid string)
+ *                     unable to extract token(s)
+ * \retval ENOMEM      insufficient memory (returned from called routines)
+ * \retval EDOM                (integer) request was out of bounds or the user has no tokens
+ * \retval ENOTCONN    user found but has no valid token(s)
+ * \retval E2BIG       token(s) do not fit in the output buffer
+ *
+ */
 DECL_PIOCTL(PGetTokens2)
 {
     struct cell *cell = NULL;
@@ -5450,6 +5463,7 @@ DECL_PIOCTL(PGetTokens2)
     char *cellName = NULL;
     afs_int32 cellNum;
     int code = 0;
+    int integer_in = 1;                /* assume integer input */
     time_t now;
     XDR xdrs;
     struct ktc_setTokenData tokenSet;
@@ -5461,11 +5475,23 @@ DECL_PIOCTL(PGetTokens2)
     memset(&tokenSet, 0, sizeof(tokenSet));
 
     /* No input data - return tokens for primary cell */
-    /* 4 octets of data is an iterator count */
+    /* 4 octets of data is PROBABLY an iterator count */
     /* Otherwise, treat as string & return tokens for that cell name */
 
     if (afs_pd_remaining(ain) == sizeof(afs_int32)) {
-       /* Integer iterator - return tokens for the n'th cell found for user */
+       char *scratch = afs_pd_where(ain);
+
+       if (scratch[3] == '\0' && strlen(scratch) == 3)
+           integer_in = 0;
+    } else {
+       integer_in = 0;
+    }
+
+    if (integer_in) {
+       /* The misleadingly-named getNthCell actually return the nth valid
+        * token found for the specified user; there can never be a gap
+        * in the ordinals at this level.
+        */
        if (afs_pd_getInt(ain, &iterator) != 0)
            return EINVAL;
        tu = getNthCell(areq->uid, iterator);
@@ -5538,7 +5564,7 @@ DECL_PIOCTL(PNFSNukeCreds)
            return EACCES;
        }
        afs_PutUser(tu, SHARED_LOCK);
-    } else if (!afs_osi_suser(acred)) {
+    } else if (!afs_osi_suser(*acred)) {
        return EACCES;
     }