180021Sjasone/* 280021Sjasone * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>. 380021Sjasone * All rights reserved. 480021Sjasone * 580021Sjasone * Redistribution and use in source and binary forms, with or without 680021Sjasone * modification, are permitted provided that the following conditions 780021Sjasone * are met: 880021Sjasone * 1. Redistributions of source code must retain the above copyright 980021Sjasone * notice(s), this list of conditions and the following disclaimer 1080021Sjasone * unmodified other than the allowable addition of one or more 1180021Sjasone * copyright notices. 1280021Sjasone * 2. Redistributions in binary form must reproduce the above copyright 1380021Sjasone * notice(s), this list of conditions and the following disclaimer in 1480021Sjasone * the documentation and/or other materials provided with the 1580021Sjasone * distribution. 1680021Sjasone * 1780021Sjasone * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 1880021Sjasone * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1980021Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2080021Sjasone * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 2180021Sjasone * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2280021Sjasone * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2380021Sjasone * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2480021Sjasone * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2580021Sjasone * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 2680021Sjasone * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 2780021Sjasone * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2880021Sjasone * 2980021Sjasone * $FreeBSD$ 3080021Sjasone * 3180021Sjasone * Test thread stack guard functionality. 3280021Sjasone */ 3380021Sjasone 3480021Sjasone#include <assert.h> 3580021Sjasone#include <stdio.h> 3680021Sjasone#include <stdlib.h> 37152598Smarcel#include <string.h> 3880021Sjasone#include <errno.h> 3980021Sjasone#include <limits.h> 4080021Sjasone#include <pthread.h> 4180021Sjasone 4280021Sjasone#define FRAME_SIZE 1024 4380021Sjasone#define FRAME_OVERHEAD 40 4480021Sjasone 4580021Sjasonestruct args 4680021Sjasone{ 4780021Sjasone void *top; /* Top of thread's initial stack frame. */ 4880021Sjasone int cur; /* Recursion depth. */ 4980021Sjasone int max; /* Maximum recursion depth. */ 5080021Sjasone}; 5180021Sjasone 5280021Sjasonevoid * 5380021Sjasonerecurse(void *args) 5480021Sjasone{ 5580021Sjasone int top; 5680021Sjasone struct args *parms = (struct args *)args; 5780021Sjasone char filler[FRAME_SIZE - FRAME_OVERHEAD]; 5880021Sjasone 5980021Sjasone /* Touch the memory in this stack frame. */ 6080021Sjasone top = 0xa5; 6180021Sjasone memset(filler, 0xa5, sizeof(filler)); 6280021Sjasone 6380021Sjasone if (parms->top == NULL) { 6480021Sjasone /* Initial stack frame. */ 6580021Sjasone parms->top = (void*)⊤ 6680021Sjasone } 6780021Sjasone 6880021Sjasone /* 6980021Sjasone * Make sure frame size is what we expect. Getting this right involves 7080021Sjasone * hand tweaking, so just print a warning rather than aborting. 7180021Sjasone */ 7280021Sjasone if (parms->top - (void *)&top != FRAME_SIZE * parms->cur) { 73152598Smarcel fprintf(stderr, 74152598Smarcel "Stack size (%ld) != expected (%ld), frame %ld\n", 75152598Smarcel (long)parms->top - (long)&top, 76152598Smarcel (long)(FRAME_SIZE * parms->cur), (long)parms->cur); 7780021Sjasone } 7880021Sjasone 7980021Sjasone parms->cur++; 8080021Sjasone if (parms->cur < parms->max) 8180021Sjasone recurse(args); 8280021Sjasone 8380021Sjasone return NULL; 8480021Sjasone} 8580021Sjasone 8680021Sjasone 8780021Sjasoneint 8880021Sjasonemain(int argc, char **argv) 8980021Sjasone{ 9080021Sjasone size_t def_stacksize, def_guardsize; 9180021Sjasone size_t stacksize, guardsize; 9280021Sjasone pthread_t thread; 9380021Sjasone pthread_attr_t attr; 9480021Sjasone struct args args; 9580021Sjasone 9680021Sjasone if (argc != 3) { 9795258Sdes fprintf(stderr, "usage: guard_b <stacksize> <guardsize>\n"); 9880021Sjasone exit(1); 9980021Sjasone } 10080021Sjasone fprintf(stderr, "Test begin\n"); 10180021Sjasone 10280021Sjasone stacksize = strtoul(argv[1], NULL, 10); 10380021Sjasone guardsize = strtoul(argv[2], NULL, 10); 10480021Sjasone 10580021Sjasone assert(pthread_attr_init(&attr) == 0); 10680021Sjasone /* 10780021Sjasone * Exercise the attribute APIs more thoroughly than is strictly 10880021Sjasone * necessary for the meat of this test program. 10980021Sjasone */ 11080021Sjasone assert(pthread_attr_getstacksize(&attr, &def_stacksize) == 0); 11180021Sjasone assert(pthread_attr_getguardsize(&attr, &def_guardsize) == 0); 11280021Sjasone if (def_stacksize != stacksize) { 11380021Sjasone assert(pthread_attr_setstacksize(&attr, stacksize) == 0); 11480021Sjasone assert(pthread_attr_getstacksize(&attr, &def_stacksize) == 0); 11580021Sjasone assert(def_stacksize == stacksize); 11680021Sjasone } 11780021Sjasone if (def_guardsize != guardsize) { 11880021Sjasone assert(pthread_attr_setguardsize(&attr, guardsize) == 0); 11980021Sjasone assert(pthread_attr_getguardsize(&attr, &def_guardsize) == 0); 12080021Sjasone assert(def_guardsize >= guardsize); 12180021Sjasone } 12280021Sjasone 12380021Sjasone /* 12480021Sjasone * Create a thread that will come just short of overflowing the thread 12580021Sjasone * stack. We need to leave a bit of breathing room in case the thread 12680021Sjasone * is context switched, and we also have to take care not to call any 12780021Sjasone * functions in the deepest stack frame. 12880021Sjasone */ 12980021Sjasone args.top = NULL; 13080021Sjasone args.cur = 0; 13180021Sjasone args.max = (stacksize / FRAME_SIZE) - 1; 13280021Sjasone fprintf(stderr, "No overflow:\n"); 13380021Sjasone assert(pthread_create(&thread, &attr, recurse, &args) == 0); 13480021Sjasone assert(pthread_join(thread, NULL) == 0); 13580021Sjasone 13680021Sjasone /* 13780021Sjasone * Create a thread that will barely of overflow the thread stack. This 13880021Sjasone * should cause a segfault. 13980021Sjasone */ 14080021Sjasone args.top = NULL; 14180021Sjasone args.cur = 0; 14280021Sjasone args.max = (stacksize / FRAME_SIZE) + 1; 14380021Sjasone fprintf(stderr, "Overflow:\n"); 14480021Sjasone assert(pthread_create(&thread, &attr, recurse, &args) == 0); 14580021Sjasone assert(pthread_join(thread, NULL) == 0); 14680021Sjasone 14780021Sjasone /* Not reached. */ 14880021Sjasone fprintf(stderr, "Unexpected success\n"); 14980021Sjasone abort(); 15080021Sjasone 15180021Sjasone return 0; 15280021Sjasone} 153