libsepol: port str_read from kernel

Rather than duplicating the following sequence:
1. Read len from file
2. alloc up space based on 1
3. read the contents into the buffer from 2
4. null terminate the buffer from 2

Use the str_read() function that is in the kernel, which
collapses steps 2 and 4. This not only reduces redundant
code, but also has the side-affect of providing a central
check on zero_or_saturated lengths from step 1 when
generating string values.

Signed-off-by: William Roberts <william.c.roberts@intel.com>
This commit is contained in:
William Roberts 2016-08-19 08:51:28 -07:00 committed by James Carter
parent fb0cc0cc64
commit fbf77104c3
5 changed files with 47 additions and 52 deletions

View File

@ -589,15 +589,8 @@ int cond_read_bool(policydb_t * p,
goto err;
len = le32_to_cpu(buf[2]);
if (zero_or_saturated(len))
if (str_read(&key, fp, len))
goto err;
key = malloc(len + 1);
if (!key)
goto err;
rc = next_entry(key, fp, len);
if (rc < 0)
goto err;
key[len] = 0;
if (p->policy_type != POLICY_KERN &&
p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {

View File

@ -793,26 +793,13 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
i);
goto cleanup;
}
len = le32_to_cpu(buf[0]);
if (zero_or_saturated(len)) {
ERR(file->handle,
"invalid module name length: 0x%"PRIx32,
len);
if (str_read(name, file, len)) {
ERR(file->handle, "%s", strerror(errno));
goto cleanup;
}
*name = malloc(len + 1);
if (!*name) {
ERR(file->handle, "out of memory");
goto cleanup;
}
rc = next_entry(*name, file, len);
if (rc < 0) {
ERR(file->handle,
"cannot get module name string (at section %u)",
i);
goto cleanup;
}
(*name)[len] = '\0';
rc = next_entry(buf, file, sizeof(uint32_t));
if (rc < 0) {
ERR(file->handle,
@ -821,25 +808,10 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type,
goto cleanup;
}
len = le32_to_cpu(buf[0]);
if (zero_or_saturated(len)) {
ERR(file->handle,
"invalid module version length: 0x%"PRIx32,
len);
if (str_read(version, file, len)) {
ERR(file->handle, "%s", strerror(errno));
goto cleanup;
}
*version = malloc(len + 1);
if (!*version) {
ERR(file->handle, "out of memory");
goto cleanup;
}
rc = next_entry(*version, file, len);
if (rc < 0) {
ERR(file->handle,
"cannot get module version string (at section %u)",
i);
goto cleanup;
}
(*version)[len] = '\0';
seen |= SEEN_MOD;
break;
default:

View File

@ -1911,19 +1911,11 @@ static int perm_read(policydb_t * p
goto bad;
len = le32_to_cpu(buf[0]);
if (zero_or_saturated(len))
if(str_read(&key, fp, len))
goto bad;
perdatum->s.value = le32_to_cpu(buf[1]);
key = malloc(len + 1);
if (!key)
goto bad;
rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0;
if (hashtab_insert(h, key, perdatum))
goto bad;

View File

@ -65,3 +65,4 @@ extern struct policydb_compat_info *policydb_lookup_compat(unsigned int version,
extern int next_entry(void *buf, struct policy_file *fp, size_t bytes) hidden;
extern size_t put_entry(const void *ptr, size_t size, size_t n,
struct policy_file *fp) hidden;
extern int str_read(char **strp, struct policy_file *fp, size_t len) hidden;

View File

@ -1639,13 +1639,16 @@ int hidden next_entry(void *buf, struct policy_file *fp, size_t bytes)
return -1;
break;
case PF_USE_MEMORY:
if (bytes > fp->len)
if (bytes > fp->len) {
errno = EOVERFLOW;
return -1;
}
memcpy(buf, fp->data, bytes);
fp->data += bytes;
fp->len -= bytes;
break;
default:
errno = EINVAL;
return -1;
}
return 0;
@ -1678,6 +1681,40 @@ size_t hidden put_entry(const void *ptr, size_t size, size_t n,
return 0;
}
/*
* Reads a string and null terminates it from the policy file.
* This is a port of str_read from the SE Linux kernel code.
*
* It returns:
* 0 - Success
* -1 - Failure with errno set
*/
int hidden str_read(char **strp, struct policy_file *fp, size_t len)
{
int rc;
char *str;
if (zero_or_saturated(len)) {
errno = EINVAL;
return -1;
}
str = malloc(len + 1);
if (!str)
return -1;
/* it's expected the caller should free the str */
*strp = str;
/* next_entry sets errno */
rc = next_entry(str, fp, len);
if (rc)
return rc;
str[len] = '\0';
return 0;
}
/*
* Read a new set of configuration data from
* a policy database binary representation file.