[PATCH] libnuma: preventing sigbus on touch beyond region

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Cliff Wickman <cpw@xxxxxxx>

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@xxxxxxx>
---
 numactl.8 |    6 ++++--
 numactl.c |   18 +++++++++++++++---
 shm.c     |   16 +++++++++++-----
 shm.h     |    4 ++--
 4 files changed, 32 insertions(+), 12 deletions(-)

Index: numactl-test.x86_64/numactl.c
===================================================================
--- numactl-test.x86_64.orig/numactl.c
+++ numactl-test.x86_64/numactl.c
@@ -356,6 +356,16 @@ void get_short_opts(struct option *o, ch
 	*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,6 +543,7 @@ int main(int ac, char **av)
 
 		case 'T': /* --touch */
 			needshm("--touch");
+			check_shmbeyond("--touch");
 			numa_police_memory(shmptr, shmlen);
 			break;
 
@@ -540,6 +551,7 @@ int main(int ac, char **av)
 			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;
 
Index: numactl-test.x86_64/shm.c
===================================================================
--- numactl-test.x86_64.orig/shm.c
+++ numactl-test.x86_64/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. */
Index: numactl-test.x86_64/shm.h
===================================================================
--- numactl-test.x86_64.orig/shm.h
+++ numactl-test.x86_64/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 */
Index: numactl-test.x86_64/numactl.8
===================================================================
--- numactl-test.x86_64.orig/numactl.8
+++ numactl-test.x86_64/numactl.8
@@ -261,8 +261,10 @@ numactl --interleave=all --shmkeyfile /t
 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 
--
To unsubscribe from this list: send the line "unsubscribe linux-numa" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]     [Devices]

  Powered by Linux