Skip to content
Permalink
Browse files

libnuma: preventing sigbus on touch beyond region

A customer used this example from the numactl.8 man page:
  numactl --offset=1G --length=1G --membind=1 --file /dev/shm/A --touch
intending to cause a 1G allocation of memory on node 1.
But they had only allocated a 1G /dev/shm/A file to begin with.
In this case numactl fails with a SIGBUS.

I don't think this example intended to imply that the --touch would
extend a tmpfs file.  Correct me if I'm wrong.

Either way, numactl should avoid dying from a SIBUS.

This patch:
- Changes the example in numactl.8 for placing a tmpfs file.
- Enhances checks of shm address/offset/length before addressing or mmap'ing
  of the shm region. This prevents invalid mmap calls and SIGBUS's.
- The options to numactl are position dependent, which can confuse a user.
  So the warning messages are clarified.

Signed-off-by: Cliff Wickman <cpw@sgi.com>
  • Loading branch information...
cpwickman authored and filbranden committed Jul 23, 2014
1 parent e328dd5 commit 59e0db3c8e5bc2d67423ab95e0e09ffc5c43d405
Showing with 32 additions and 12 deletions.
  1. +4 −2 numactl.8
  2. +15 −3 numactl.c
  3. +11 −5 shm.c
  4. +2 −2 shm.h
@@ -261,8 +261,10 @@ numactl --interleave=all --shmkeyfile /tmp/shmkey
Interleave all of the sysv shared memory region specified by
/tmp/shmkey over all nodes.

numactl --offset=1G --length=1G --membind=1 --file /dev/shm/A --touch
Bind the second gigabyte in the tmpfs file /dev/shm/A to node 1.
Place a tmpfs file on 2 nodes:
numactl --membind=2 dd if=/dev/zero of=/dev/shm/A bs=1M count=1024
numactl --membind=3 dd if=/dev/zero of=/dev/shm/A seek=1024 bs=1M count=1024


numactl --localalloc /dev/shm/file
Reset the policy for the shared memory file
@@ -356,6 +356,16 @@ void get_short_opts(struct option *o, char *s)
*s = '\0';
}

void check_shmbeyond(char *msg)
{
if (shmoffset >= shmlen) {
fprintf(stderr,
"numactl: region offset %#llx beyond its length %#llx at %s\n",
shmoffset, shmlen, msg);
exit(1);
}
}

int main(int ac, char **av)
{
int c, i, nnodes=0;
@@ -478,13 +488,13 @@ int main(int ac, char **av)
case 'S': /* --shm */
check_cpubind(did_cpubind);
nopolicy();
attach_sysvshm(optarg);
attach_sysvshm(optarg, "--shm");
shmattached = 1;
break;
case 'f': /* --file */
check_cpubind(did_cpubind);
nopolicy();
attach_shared(optarg);
attach_shared(optarg, "--file");
shmattached = 1;
break;
case 'L': /* --length */
@@ -533,13 +543,15 @@ int main(int ac, char **av)

case 'T': /* --touch */
needshm("--touch");
check_shmbeyond("--touch");
numa_police_memory(shmptr, shmlen);
break;

case 'V': /* --verify */
needshm("--verify");
if (set_policy < 0)
complain("Need a policy first to verify");
check_shmbeyond("--verify");
numa_police_memory(shmptr, shmlen);
if (!mask)
complain("Need a mask to verify");
@@ -551,7 +563,7 @@ int main(int ac, char **av)
usage();
}
}

av += optind;
ac -= optind;

16 shm.c
@@ -61,12 +61,18 @@ long huge_page_size(void)
return getpagesize();
}

static void check_region(void)
static void check_region(char *opt)
{
if (((unsigned long)shmptr % shm_pagesize) || (shmlen % shm_pagesize)) {
fprintf(stderr, "numactl: policy region not page aligned\n");
exit(1);
}
if (!shmlen) {
fprintf(stderr,
"numactl: policy region length not specified before %s\n",
opt);
exit(1);
}
}

static key_t sysvkey(char *name)
@@ -89,7 +95,7 @@ static key_t sysvkey(char *name)
}

/* Attach a sysv style shared memory segment. */
void attach_sysvshm(char *name)
void attach_sysvshm(char *name, char *opt)
{
struct shmid_ds s;
key_t key = sysvkey(name);
@@ -120,11 +126,11 @@ void attach_sysvshm(char *name)

shm_pagesize = (shmflags & SHM_HUGETLB) ? huge_page_size() : getpagesize();

check_region();
check_region(opt);
}

/* Attach a shared memory file. */
void attach_shared(char *name)
void attach_shared(char *name, char *opt)
{
struct stat64 st;

@@ -150,7 +156,7 @@ void attach_shared(char *name)

shm_pagesize = st.st_blksize;

check_region();
check_region(opt);

/* RED-PEN For shmlen > address space may need to map in pieces.
Left for some poor 32bit soul. */
4 shm.h
@@ -9,8 +9,8 @@ extern int shmflags;

extern void dump_shm(void);
extern void dump_shm_nodes(void);
extern void attach_shared(char *);
extern void attach_sysvshm(char *);
extern void attach_shared(char *, char *);
extern void attach_sysvshm(char *, char *);
extern void verify_shm(int policy, struct bitmask *);

/* in numactl.c */

0 comments on commit 59e0db3

Please sign in to comment.
You can’t perform that action at this time.