static int
afs_getsysname(struct vrequest *areq, struct vcache *adp,
- char *bufp, int *num, char **sysnamelist[])
+ char *bufp, size_t bufsize, int *num, char **sysnamelist[])
{
- struct unixuser *au;
- afs_int32 error;
+ struct unixuser *au = NULL;
+ afs_int32 error, code = -1;
+ size_t rlen;
AFS_STATCNT(getsysname);
*sysnamelist = afs_sysnamelist;
- if (!afs_nfsexporter)
- strcpy(bufp, (*sysnamelist)[0]);
- else {
+ if (!afs_nfsexporter) {
+ rlen = strlcpy(bufp, (*sysnamelist)[0], bufsize);
+ if (rlen >= bufsize)
+ goto done;
+ } else {
au = afs_GetUser(areq->uid, adp->f.fid.Cell, READ_LOCK);
if (au->exporter) {
error = EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num, 0);
if (error) {
- strcpy(bufp, "@sys");
- afs_PutUser(au, READ_LOCK);
- return -1;
+ strlcpy(bufp, "@sys", bufsize);
+ goto done;
} else {
- strcpy(bufp, (*sysnamelist)[0]);
+ rlen = strlcpy(bufp, (*sysnamelist)[0], bufsize);
+ if (rlen >= bufsize)
+ goto done;
}
- } else
- strcpy(bufp, afs_sysname);
- afs_PutUser(au, READ_LOCK);
+ } else {
+ rlen = strlcpy(bufp, afs_sysname, bufsize);
+ if (rlen >= bufsize)
+ goto done;
+ }
}
- return 0;
+ code = 0;
+ done:
+ if (au != NULL)
+ afs_PutUser(au, READ_LOCK);
+ return code;
}
void
state->name_size = MAXSYSNAME;
state->name = osi_AllocLargeSpace(state->name_size);
state->index =
- afs_getsysname(areq, avc, state->name, &num, sysnamelist);
+ afs_getsysname(areq, avc, state->name, state->name_size, &num,
+ sysnamelist);
} else {
state->offset = -1;
state->name_size = 0;
struct sysname_info *state)
{
int num = afs_sysnamecount;
- char **sysnamelist[MAXNUMSYSNAMES];
+ char **sysnamelist[MAXNUMSYSNAMES], *buf;
+ size_t bsz;
if (state->index == -1)
return 0; /* No list */
/*Move to the end of the string */ ;
if ((tname > state->name + 4) && (AFS_EQ_ATSYS(tname - 4))) {
- state->offset = (tname - 4) - state->name;
- tname = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
- strncpy(tname, state->name, state->offset);
- state->name = tname;
- state->name_size = AFS_LRALLOCSIZ;
+ int idx;
+ size_t len, bufsize = AFS_LRALLOCSIZ;
+
+ len = (tname - 4) - state->name;
+ if (len >= bufsize) {
+ return 0;
+ }
+
+ tname = osi_AllocLargeSpace(bufsize);
+ /* intentionally truncating state->name */
+ strlcpy(tname, state->name, len + 1);
+
+ buf = tname + len;
+ bsz = bufsize - len;
num = 0;
- state->index =
- afs_getsysname(areq, avc, state->name + state->offset, &num,
- sysnamelist);
+ idx = afs_getsysname(areq, avc, buf, bsz, &num, sysnamelist);
+ if (idx == -1) {
+ osi_FreeLargeSpace(tname);
+ return 0;
+ }
+ /*
+ * If we got here, state->name isn't pointing to any dynamically
+ * allocated memory. In other words, state->name_size must be 0.
+ */
+ state->name = tname;
+ state->offset = len;
+ state->name_size = bufsize;
+ state->index = idx;
+
return 1;
} else
return 0; /* .*@sys doesn't match either */
if (++(state->index) >= num || !(*sysnamelist)[(unsigned int)state->index])
return 0; /* end of list */
}
- strcpy(state->name + state->offset, (*sysnamelist)[(unsigned int)state->index]);
+ /*
+ * If we got here, state->name was allocated by the AtSys iterator. In other
+ * words, state->name_size must be greater than 0.
+ */
+ buf = state->name + state->offset;
+ bsz = state->name_size - state->offset;
+ if (strlcpy(buf, (*sysnamelist)[(unsigned int)state->index], bsz) >= bsz) {
+ state->index = -1;
+ return 0;
+ }
return 1;
}