]> git.saurik.com Git - apple/xnu.git/blobdiff - tools/tests/xnu_quick_test/tests.c
xnu-2050.7.9.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / tests.c
index a916b6a384a8fa71933b9d8fd6bf425b5a9e7090..cf2867e8ac541b294af28353630753e3f95f8c4b 100644 (file)
 #include <sys/msg.h>           /* for message queue tests */
 #include <sys/syscall.h>       /* for get / settid */
 #include <sys/sysctl.h>                /* for determining hw */
+#include <sys/kas_info.h>      /* for kas_info() */
 #include <AvailabilityMacros.h>        /* for determination of Mac OS X version (tiger, leopard, etc.) */
 #include <libkern/OSByteOrder.h> /* for OSSwap32() */
 #include <mach/mach.h>
 
+
 extern char            g_target_path[ PATH_MAX ];
 extern int             g_skip_setuid_tests;
-extern int             g_is_under_rosetta;
 extern int             g_is_single_user;
 
 
@@ -893,11 +894,19 @@ test_passed_exit:
  */
 int access_chmod_fchmod_test( void * the_argp )
 {
-       int                     my_err;
-       int                     my_fd = -1;
+       int             error_occurred;
+       int             my_err;
+       int             my_fd = -1;
+
        char *          my_pathp = NULL;
-       struct stat             my_sb;
-       kern_return_t           my_kr;
+
+       uid_t           euid,ruid;
+       struct stat     my_sb;
+
+       FILE *          file_handle;
+
+       kern_return_t   my_kr;
+
 
         my_kr = vm_allocate((vm_map_t) mach_task_self(), (vm_address_t*)&my_pathp, PATH_MAX, VM_FLAGS_ANYWHERE);
         if(my_kr != KERN_SUCCESS){
@@ -915,6 +924,7 @@ int access_chmod_fchmod_test( void * the_argp )
                goto test_failed_exit;
        }
        
+       
        /* test chmod */
        my_err = chmod( my_pathp, S_IRWXU );
        if ( my_err == -1 ) {
@@ -940,17 +950,10 @@ int access_chmod_fchmod_test( void * the_argp )
                
                /* special case when running as root - we get back EPERM when running as root */
                my_err = errno;
-#if !TARGET_OS_EMBEDDED
                if ( ( tmp == 0 && my_err != EPERM) || (tmp != 0 && my_err != EACCES) ) {
                        printf( "access failed with errno %d - %s. \n", my_err, strerror( my_err ) );
                        goto test_failed_exit;
                }
-#else
-               if ( ( tmp == 0 && my_err != EACCES) || (tmp != 0 && my_err != EACCES) ) {
-                       printf( "access failed with errno %d - %s. \n", my_err, strerror( my_err ) );
-                       goto test_failed_exit;
-               }
-#endif
        }
 
        /* verify correct modes are set */
@@ -965,7 +968,83 @@ int access_chmod_fchmod_test( void * the_argp )
                printf( "chmod call appears to have failed.  stat shows incorrect values in st_mode! \n" );
                goto test_failed_exit;
        }
+       
+       
+       /*  another test for the access system call  -- refer ro radar# 6725311 */
+
+#if !TARGET_OS_EMBEDDED        
+
+       /*
+        * This test makes sure that the access system call does not give the current user extra
+        * permissions on files the current user does not own. From radar #6725311, this could
+        * happen when the current user calls access() on a file owned by the current user in
+        * the same directory as the other files not owned by the current user.
+        * 
+        * Note: This test expects that the effective uid (euid) is set to root.
+        *
+        */
+
+       /* Create a file that root owns  */
+       file_handle = fopen(FILE_NOTME, "w");
+       fclose(file_handle);
+
+       /* Currently running as root (through setreuid manipulation), switch to running as the current user. */
+       euid = geteuid();
+       ruid = getuid();
+       setreuid(ruid, ruid);
+
+       /* Create a file that the current user owns  */
+       file_handle = fopen(FILE_ME, "w");
+       fclose(file_handle);
+
+       error_occurred = 0;
+
+       /* Try to remove the file owned by root (this should fail). */
+       my_err = unlink(FILE_NOTME);
+
+       if (my_err < 0) {
+               my_err = errno;
+       }
+
+       if (my_err == 0) {
+               printf("Unresolved: First attempt deleted '" FILE_NOTME "'! \n");
+               error_occurred = 1;
+       } else {
+               printf("Status: First attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
+
+               /* Set _DELETE_OK on a file that the current user owns */
+               access(FILE_ME, _DELETE_OK);
+
+               /* Try to remove the file owned by root again (should give us: EPERM [13]) */
+               my_err = unlink(FILE_NOTME);
+
+               if (my_err < 0) {
+                   my_err = errno;
+               }
+
+               if (my_err == 0) {
+                       printf("Failed: Second attempt deleted '" FILE_NOTME "'!\n");
+                       error_occurred = 1;
+               } else if (my_err == 13) {
+                       printf("Passed: Second attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
+               } else {
+                       printf("Failed: Second attempt to delete '" FILE_NOTME "' failed with error %d - %s.\n", my_err, strerror( my_err ));
+                       error_occurred = 1;
+               }
+       }
+
+       /* Reset to running as root */
+       setreuid(ruid, euid);
+
+       if(error_occurred == 1) {
+               goto test_failed_exit;
+       }
 
+#endif
+
+       /* end of test*/
+       
+       
        /* test fchmod */
        my_fd = open( my_pathp, O_RDONLY, 0 );
        if ( my_fd == -1 ) {
@@ -1009,6 +1088,26 @@ test_passed_exit:
        return( my_err );
 }
 
+#if !TARGET_OS_EMBEDDED
+static bool _prime_groups(void)
+{
+       /*
+        * prime groups with a known list to ensure consistent test behavior
+        */
+       
+       gid_t   my_exp_groups[] = { getegid(), 20, 61, 12 };
+       int             my_err;
+
+       my_err = setgroups( ( sizeof(my_exp_groups) / sizeof(*my_exp_groups) ), &my_exp_groups[0] );
+       if ( my_err == -1 ) {
+               printf( "initial setgroups call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
+               return false;
+       }
+
+       return true;
+}
+#endif
+
 /*  **************************************************************************************************************
  *     Test chown, fchown, lchown, lstat, readlink, symlink system calls.
  *  **************************************************************************************************************
@@ -1060,6 +1159,10 @@ int chown_fchown_lchown_lstat_symlink_test( void * the_argp )
                goto test_failed_exit;
        }
        
+       if ( !_prime_groups() ) {
+               goto test_failed_exit;
+       }
+       
        /* set up by getting a list of groups */
        my_group_count = getgroups( NGROUPS_MAX, &my_groups[0] );
        
@@ -1219,6 +1322,8 @@ struct vol_attr_buf {
 #pragma pack()
 typedef struct vol_attr_buf vol_attr_buf;
 
+#define STATFS_TEST_PATH       "/tmp"
+
 int fs_stat_tests( void * the_argp )
 {
        int                     my_err, my_count, i;
@@ -1255,7 +1360,7 @@ int fs_stat_tests( void * the_argp )
         }
 
        my_statfsp = (struct statfs *) my_bufferp;
-       my_err = statfs( "/", my_statfsp );
+       my_err = statfs( STATFS_TEST_PATH, my_statfsp );
        if ( my_err == -1 ) {
                printf( "statfs call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
                goto test_failed_exit;
@@ -1289,7 +1394,7 @@ int fs_stat_tests( void * the_argp )
 #if !TARGET_OS_EMBEDDED
        /* now try statfs64 */
        my_statfs64p = (struct statfs64 *) my_buffer64p;
-       my_err = statfs64( "/", my_statfs64p );
+       my_err = statfs64( STATFS_TEST_PATH, my_statfs64p );
        if ( my_err == -1 ) {
                printf( "statfs64 call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
                goto test_failed_exit;
@@ -1338,8 +1443,8 @@ int fs_stat_tests( void * the_argp )
                }
        }
        
-       /* open kernel to use as test file for fstatfs */
-       my_fd = open( "/mach_kernel", O_RDONLY, 0 );
+       /* open to use as test file for fstatfs */
+       my_fd = open( STATFS_TEST_PATH, O_RDONLY, 0 );
        if ( my_fd == -1 ) {
                printf( "open call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
                goto test_failed_exit;
@@ -1384,7 +1489,7 @@ int fs_stat_tests( void * the_argp )
        } 
 
        /* try again with statfs */
-       my_err = statfs( "/mach_kernel", my_statfsp );
+       my_err = statfs( STATFS_TEST_PATH , my_statfsp );
        if ( my_err == -1 ) {
                printf( "statfs call failed.  got errno %d - %s. \n", errno, strerror( errno ) );
                goto test_failed_exit;
@@ -1942,12 +2047,8 @@ int execve_kill_vfork_test( void * the_argp )
        }
        
        if (get_architecture() == INTEL) {
-               int ppc_fail_flag = 0;
                struct stat sb;
 
-               if (stat("/usr/libexec/oah/translate", &sb))
-                       ppc_fail_flag = 1;
-
                if (bits == 64 && sizeof(long) == 8) {
                        /*
                         * Running on x86_64 hardware and running in 64-bit mode.
@@ -1970,19 +2071,12 @@ int execve_kill_vfork_test( void * the_argp )
                        argvs[0] = "launch-i386";
                        if (do_execve_test("helpers/launch-i386", argvs, NULL, 1) != 0)         goto test_failed_exit;
 
-                       /* Test posix_spawn for i386, x86_64, and ppc (should succeed) */
+                       /* Test posix_spawn for i386, x86_64 (should succeed) */
                        errmsg = NULL;
                        if (do_spawn_test(CPU_TYPE_I386, 0))
                                goto test_failed_exit;
                        if (do_spawn_test(CPU_TYPE_X86_64, 0))
                                goto test_failed_exit;
-                       /*
-                        * Note: rosetta is no go in single-user mode
-                        */
-                       if (!g_is_single_user) {
-                               if (do_spawn_test(CPU_TYPE_POWERPC, ppc_fail_flag))
-                                       goto test_failed_exit;
-                       }
                }
                else if (bits == 64 && sizeof(long) == 4) {
                        /*
@@ -2006,19 +2100,12 @@ int execve_kill_vfork_test( void * the_argp )
                        argvs[0] = "launch-x86_64";
                        if (do_execve_test("helpers/launch-x86_64", argvs, NULL, 1) != 0)       goto test_failed_exit;
 
-                       /* Test posix_spawn for i386, x86_64, and ppc (should succeed) */
+                       /* Test posix_spawn for i386, x86_64 (should succeed) */
                        errmsg = NULL;
                        if (do_spawn_test(CPU_TYPE_I386, 0))
                                goto test_failed_exit;
                        if (do_spawn_test(CPU_TYPE_X86_64, 0))
                                goto test_failed_exit;
-                       /*
-                        * Note: rosetta is no go in single-user mode
-                        */
-                       if (!g_is_single_user) {
-                               if (do_spawn_test(CPU_TYPE_POWERPC, ppc_fail_flag))
-                                       goto test_failed_exit;
-                       }
                }
                else if (bits == 32) {
                        /* Running on i386 hardware. Check cases 4. */
@@ -2026,61 +2113,14 @@ int execve_kill_vfork_test( void * the_argp )
                        argvs[0] = "sleep-i386";
                        if (do_execve_test("helpers/sleep-i386", argvs, NULL, 1))               goto test_failed_exit;
 
-                       /* Test posix_spawn for x86_64 (should fail), i386, and ppc (should succeed) */
+                       /* Test posix_spawn for x86_64 (should fail), i386 (should succeed) */
                        errmsg = NULL;
                        if (do_spawn_test(CPU_TYPE_X86_64, 1))
                                goto test_failed_exit;
                        if (do_spawn_test(CPU_TYPE_I386, 0))
                                goto test_failed_exit;
-                       /*
-                        * Note: rosetta is no go in single-user mode
-                        */
-                       if (!g_is_single_user) {
-                               if (do_spawn_test(CPU_TYPE_POWERPC, ppc_fail_flag))
-                                       goto test_failed_exit;
-                       }
-               }
-       }
-       else if (get_architecture() == POWERPC) {
-               if      (bits == 64 && sizeof(long) == 8) {
-                       /*
-                        * Running on PPC64 hardware and running in 64-bit mode.
-                        * No longer supported on SnowLeopard.
-                        */ 
-                       errmsg = "runnning ppc64 on snowleopard";
-                       goto test_failed_exit;
-               }
-               else if (bits == 64 && sizeof(long) == 4) {
-                       /*
-                        * Running as PPC on PPC64 hardware or under Rosetta on x86_64 hardware.
-                        * Check cases 4, 5, 6 and fork a child to check 1, 2, 3. 
-                        */ 
-                       errmsg = "execve failed: from ppc forking and exec()ing ppc process.\n";
-                       argvs[0] = "sleep-ppc32";
-                       if (do_execve_test("helpers/sleep-ppc32", argvs, NULL, 0))      goto test_failed_exit;
-
-                       /* Test posix_spawn for i386 and ppc */
-                       errmsg = NULL;
-                       if (do_spawn_test(CPU_TYPE_I386, (g_is_under_rosetta ? 0 : 1)))
-                               goto test_failed_exit;
-                       if (do_spawn_test(CPU_TYPE_POWERPC, 0))
-                               goto test_failed_exit;
-               }
-               else if (bits == 32) {
-                       /* Running on ppc hardware. Check cases 4. */
-                       errmsg = "execve failed: from ppc forking and exec()ing 32 bit ppc process.\n";
-                       argvs[0] = "sleep-ppc32";
-                       if (do_execve_test("helpers/sleep-ppc32", argvs, NULL, 1))              goto test_failed_exit;  
-                       /* Test posix_spawn for i386 (should fail) and ppc (should succeed) */
-                       errmsg = NULL;
-                        /* when under Rosetta, this process is CPU_TYPE_POWERPC, but the system should be able to run CPU_TYPE_I386 binaries */
-                       if (do_spawn_test(CPU_TYPE_I386, (g_is_under_rosetta ? 0 : 1)))
-                               goto test_failed_exit;
-                       if (do_spawn_test(CPU_TYPE_POWERPC, 0))
-                               goto test_failed_exit;
                }
-       }
-       else if(get_architecture() == ARM) {
+       }else if(get_architecture() == ARM) {
                if      (bits == 32) {
 
                        /* Running on arm hardware. Check cases 2. */
@@ -2134,6 +2174,10 @@ int groups_test( void * the_argp )
        my_real_gid = getgid( );
        my_effective_gid = getegid( );
 
+       if ( !_prime_groups() ) {
+               goto test_failed_exit;
+       }
+       
        /* start by getting list of groups the current user belongs to */
        my_orig_group_count = getgroups( NGROUPS_MAX, &my_groups[0] );
 
@@ -2914,36 +2958,11 @@ int acct_test( void * the_argp )
        /* first letters in ac_comm should match the name of the executable */
        if ( getuid( ) != my_acctp->ac_uid || getgid( ) != my_acctp->ac_gid ||
                        my_acctp->ac_comm[0] != 't' || my_acctp->ac_comm[1] != 'r' ) {
-               if (g_is_under_rosetta) {
-                       // on x86 systems, data written by kernel to accounting info file is little endian; 
-                        // but Rosetta processes expects it to be big endian; so swap the uid for our test
-                       if ( getuid( ) != OSSwapInt32(my_acctp->ac_uid) || 
-                                       getgid( ) != OSSwapInt32(my_acctp->ac_gid) ||
-                                       my_acctp->ac_comm[0] != 't' || 
-                                       my_acctp->ac_comm[1] != 'r' ) {
-                               printf( "accounting data does not look correct under Rosetta:\n" );
-                               printf( "------------------------\n" );
-                               printf( "my_acctp->ac_uid = %lu (should be: %lu)\n",
-                                       (unsigned long) OSSwapInt32( my_acctp->ac_uid ), (unsigned long) getuid() );
-                               printf( "my_acctp->ac_gid = %lu (should be: %lu)\n", 
-                                       (unsigned long) OSSwapInt32( my_acctp->ac_gid ), (unsigned long) getgid() );
-
-                               print_acct_debug_strings(my_acctp->ac_comm);
-                       }
-                       else {
-                               // is cool under Rosetta 
-                               my_err = 0;
-                               goto test_passed_exit;
-                       }
-               }
-               else {
-                       printf( "accounting data does not look correct:\n" );
                        printf( "------------------------\n" );
                        printf( "my_acctp->ac_uid = %lu (should be: %lu)\n", (unsigned long) my_acctp->ac_uid, (unsigned long) getuid() );
                        printf( "my_acctp->ac_gid = %lu (should be: %lu)\n", (unsigned long) my_acctp->ac_gid, (unsigned long) getgid() );
 
                        print_acct_debug_strings(my_acctp->ac_comm);
-               }
                
                goto test_failed_exit;
        }
@@ -3320,6 +3339,7 @@ int fcntl_test( void * the_argp )
 {
        int                     my_err, my_result, my_tmep;
        int                     my_fd = -1;
+       int                     my_newfd = -1;
        char *          my_pathp = NULL;
        kern_return_t           my_kr;
 
@@ -3376,7 +3396,61 @@ int fcntl_test( void * the_argp )
                printf( "fcntl - F_SETFD failed to set FD_CLOEXEC correctly!!! \n" );
                goto test_failed_exit;
        }
-       
+
+       /* dup it to a new fd with FD_CLOEXEC forced on */
+
+       my_result = fcntl( my_fd, F_DUPFD_CLOEXEC, 0);
+       if ( my_result == -1 ) {
+               printf( "fcntl - F_DUPFD_CLOEXEC - failed with error %d - \"%s\" \n", errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+       my_newfd = my_result;
+
+       /* check to see that it too is marked with FD_CLOEXEC */
+
+       my_result = fcntl( my_newfd, F_GETFD, 0);
+       if ( my_result == -1 ) {
+               printf( "fcntl - F_GETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+       if ( (my_result & FD_CLOEXEC) == 0 ) {
+               printf( "fcntl - F_DUPFD_CLOEXEC failed to set FD_CLOEXEC!!! \n" );
+               goto test_failed_exit;
+       }
+
+       close( my_newfd );
+       my_newfd = -1;
+
+#if !TARGET_OS_EMBEDDED /* This section of the test is specific for the desktop platform, refer <rdar://problem/8850905>*/
+       /* While we're here, dup it via an open of /dev/fd/<fd> .. */
+
+       {
+               char devfdpath[PATH_MAX];
+
+               (void) snprintf( devfdpath, sizeof (devfdpath),
+                       "/dev/fd/%u", my_fd );
+               my_result = open( devfdpath, O_RDONLY | O_CLOEXEC );
+       }
+       if ( my_result == -1 ) {
+               printf( "open call failed on /dev/fd/%u with error %d - \"%s\" \n", my_fd, errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+       my_newfd = my_result;
+
+       /* check to see that it too is marked with FD_CLOEXEC */
+
+       my_result = fcntl( my_newfd, F_GETFD, 0);
+       if ( my_result == -1 ) {
+               printf( "fcntl - F_GETFD - failed with error %d - \"%s\" \n", errno, strerror( errno) );
+               goto test_failed_exit;
+       }
+       if ( (my_result & FD_CLOEXEC) == 0 ) {
+               printf( "fcntl - O_CLOEXEC open of /dev/fd/%u failed to set FD_CLOEXEC!!! \n", my_fd );
+               goto test_failed_exit;
+       }
+       close ( my_newfd );
+       my_newfd = -1;
+#endif
        my_err = 0;
        goto test_passed_exit;
 
@@ -3384,6 +3458,8 @@ test_failed_exit:
        my_err = -1;
        
 test_passed_exit:
+       if ( my_newfd != -1)
+               close ( my_newfd );
        if ( my_fd != -1 )
                close( my_fd );
        if ( my_pathp != NULL ) {
@@ -4407,6 +4483,7 @@ typedef struct packed_result * packed_result_p;
 
 int searchfs_test( void * the_argp )
 {
+#if !TARGET_OS_EMBEDDED
        int                                             my_err, my_items_found = 0, my_ebusy_count;
        char *                                  my_pathp = NULL;
     unsigned long                      my_matches;
@@ -4601,6 +4678,10 @@ test_passed_exit:
                vm_deallocate(mach_task_self(), (vm_address_t)my_pathp, PATH_MAX);      
         }
        return( my_err );
+#else
+       printf( "\t--> Not supported on EMBEDDED TARGET\n" );
+       return 0;
+#endif
 }
 
 
@@ -4612,7 +4693,6 @@ test_passed_exit:
  */
 int aio_tests( void * the_argp )
 {
-#if !TARGET_OS_EMBEDDED
        int                                     my_err, i;
        char *                          my_pathp;
        struct aiocb *          my_aiocbp;
@@ -4877,10 +4957,6 @@ test_passed_exit:
                }
        }
        return( my_err );
-#else
-       printf( "\t--> Not supported on EMBEDDED TARGET\n" );
-       return 0;
-#endif
 }
 
 
@@ -4993,6 +5069,7 @@ test_passed_exit:
 }
 
 
+
 /*  **************************************************************************************************************
  *     Test execution from data and stack areas.
  *  **************************************************************************************************************
@@ -5001,7 +5078,11 @@ int data_exec_tests( void * the_argp )
 {
        int my_err = 0;
        int arch, bits;
+       posix_spawnattr_t attrp;
+       char *argv[] = { "helpers/data_exec32nonxspawn", NULL };
 
+       int my_pid, my_status, ret;
+       
        if ((arch = get_architecture()) == -1) {
                printf("data_exec_test: couldn't determine architecture\n");
                goto test_failed_exit;
@@ -5026,11 +5107,21 @@ int data_exec_tests( void * the_argp )
                        printf("data_exec-i386 failed\n");
                        goto test_failed_exit;
                }
-       }
-
-       if (arch == POWERPC) {
-               if (system("arch -arch ppc helpers/data_exec") != 0) {
-                       printf("data_exec-ppc failed\n");
+               
+               posix_spawnattr_init(&attrp);
+               posix_spawnattr_setflags(&attrp, _POSIX_SPAWN_ALLOW_DATA_EXEC );
+               ret = posix_spawn(&my_pid, "helpers/data_exec32nonxspawn", NULL, &attrp, argv, NULL);
+               if (ret) {
+                       printf("data_exec-i386 failed in posix_spawn %s\n", strerror(errno));
+                       goto test_failed_exit;
+               }
+               ret = wait4(my_pid, &my_status, 0, NULL);
+               if (ret == -1) {
+                       printf("data_exec-i386 wait4 failed with errno %d - %s\n", errno, strerror(errno));
+                       goto test_failed_exit;
+               }
+               if (WEXITSTATUS(my_status) != 0) {
+                       printf("data_exec-i386 _POSIX_SPAWN_ALLOW_DATA_EXEC failed\n");
                        goto test_failed_exit;
                }
        }
@@ -5046,6 +5137,80 @@ test_passed_exit:
        return my_err;
 }
 
+/*  **************************************************************************************************************
+ *     Test KASLR-related functionality
+ *  **************************************************************************************************************
+ */
+int kaslr_test( void * the_argp )
+{
+       int result = 0;
+       uint64_t slide = 0;
+       size_t size;
+       int slide_enabled;
+
+       size = sizeof(slide_enabled);
+       result = sysctlbyname("kern.slide", &slide_enabled, &size, NULL, 0);
+       if (result != 0) {
+               printf("sysctlbyname(\"kern.slide\") failed with errno %d\n", errno);
+               goto test_failed_exit;
+       }
+
+       /* Test positive case first */
+       size = sizeof(slide);
+       result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size);
+       if (result == 0) {
+               /* syscall supported, slide must be non-zero if running latest xnu and KASLR is enabled */
+               if (slide_enabled && (slide == 0)) {
+                       printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size) reported slide of 0x%016llx\n", slide);
+                       goto test_failed_exit;
+               }
+               if (size != sizeof(slide)) {
+                       printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size) reported size of %lu\n", size);
+                       goto test_failed_exit;
+               }
+       } else {
+               /* Only ENOTSUP is allowed. If so, assume all calls will be unsupported */
+               if (errno == ENOTSUP) {
+                       return 0;
+               } else {
+                       printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &slide, &size) returned unexpected errno (errno %d)\n", errno);
+                       goto test_failed_exit;
+               }
+       }
+       
+       /* Negative cases for expected failures */
+       size = sizeof(slide);
+       result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL /* EFAULT */, &size);
+       if ((result == 0) || (errno != EFAULT)) {
+               printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, &size) returned unexpected success or errno (result %d errno %d)\n", result, errno);
+               goto test_failed_exit;
+       }
+
+       size = sizeof(slide) + 1; /* EINVAL */
+       result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, &size);
+       if ((result == 0) || (errno != EINVAL)) {
+               printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, &size+1) returned unexpected success or errno (result %d errno %d)\n", result, errno);
+               goto test_failed_exit;
+       }
+
+       result = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL /* EFAULT */, NULL /* EFAULT */);
+       if ((result == 0) || (errno != EFAULT)) {
+               printf("kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, NULL, NULL) returned unexpected success or errno (result %d errno %d)\n", result, errno);
+               goto test_failed_exit;
+       }
+
+       size = sizeof(slide);
+       result = kas_info(KAS_INFO_MAX_SELECTOR /* EINVAL */, &slide, &size);
+       if ((result == 0) || (errno != EINVAL)) {
+               printf("kas_info(KAS_INFO_MAX_SELECTOR, &slide, &size) returned unexpected success or errno (result %d errno %d)\n", result, errno);
+               goto test_failed_exit;
+       }
+
+       return 0;
+
+test_failed_exit:
+       return -1;
+}
 
 #if TEST_SYSTEM_CALLS