Fwd: Reporting some Kernel Panics

Jeff Burke jburke at redhat.com
Mon Jul 11 15:01:31 UTC 2005


Linda Knippers wrote:

>>  I can write a test that will try and read all files in /proc. May or 
>> may not provide
>> any data. 
>
>
> Attached is the test program they were running.  Kris Wilson sent it
> to me.  I've tried it a few times on an ia64 system with the .74 kernel
> but haven't seen any problems.  Maybe you'll have better luck.
>
> -- ljk
>
>------------------------------------------------------------------------
>
>##########################################################################
>#   Copyright (C) International Business Machines  Corp., 2004
>#
>#   This program is free software;  you can redistribute it and/or modify
>#   it under the terms of the GNU General Public License as published by
>#   the Free Software Foundation; either version 2 of the License, or
>#   (at your option) any later version.
>#
>#   This program is distributed in the hope that it will be useful,
>#   but WITHOUT ANY WARRANTY;  without even the implied warranty of
>#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>#   the GNU General Public License for more details.
>#
>#   You should have received a copy of the GNU General Public License
>#   along with this program;  if not, write to the Free Software
>#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>#
>#
>#
>#  FILE   : Makefile
>#
>#  PURPOSE: The default "all" target uses the gcc compiler to compile all
>#           test files in the current directory.
>#
>#           The "clean" target removes all files the end in ".o" (object
>#           files).
>#
>#
>#  HISTORY:
>#    10/04 originated by Dan Jones (danjones at us.ibm.com)
>#
>##########################################################################
>TOPDIR= ../..
>LOG=log
>CC=gcc 
>EXE=testfileperms
>DIRS= proc \
>	sys
>
>all:: $(EXE)
>
>run:: all
>	-grep "^fpermu" /etc/passwd | awk -F: '{print $$1}' | xargs -i userdel -r {}
>	-grep "^fpermg" /etc/group | awk -F: '{print $$1}' | xargs -i groupdel {}
>	useradd fpermu &>/dev/null
>	groupadd fpermg &>/dev/null
>	-for i in $(DIRS); do ./$(EXE) /$$i fpermu fpermg &>$(EXE).$$i.$(LOG); done
>	-for i in $(DIRS); do grep "FAIL" $(EXE).$$i.$(LOG) > $(EXE).$$i.FAIL; done
>	-for i in $(DIRS); do grep "SKIP" $(EXE).$$i.$(LOG) > $(EXE).$$i.SKIP; done
>
>	groupdel fpermg &>/dev/null
>	userdel -fr fpermu &>/dev/null
>
>rmlogs::
>	rm -f *log &>/dev/null
>	rm -f *FAIL &>/dev/null
>	rm -f *SKIP &>/dev/null
>
>clean::
>	rm -f $(EXE)
>
># include $(TOPDIR)/rules.mk
>  
>
>------------------------------------------------------------------------
>
>/**********************************************************************
>**   Copyright (C) International Business Machines  Corp., 2004
>**
>**   This program is free software;  you can redistribute it and/or modify
>**   it under the terms of the GNU General Public License as published by
>**   the Free Software Foundation; either version 2 of the License, or
>**   (at your option) any later version.
>**
>**   This program is distributed in the hope that it will be useful,
>**   but WITHOUT ANY WARRANTY;  without even the implied warranty of
>**   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
>**   the GNU General Public License for more details.
>**
>**   You should have received a copy of the GNU General Public License
>**   along with this program;  if not, write to the Free Software
>**   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>**
>**
>**
>**  FILE   : testfileperms.c
>**
>**  PURPOSE: The purpose of this test is to verify the file permissions
>**           of all files under a given directory. The test makes 2 passes
>**           through all the files. 
>**           Pass 1: 
>**                  Using the existing file attributes, verify file
>**                  access as the file owner, group owner and other.
>**                  The results of "open" are used to determine access.
>**                  If the file owner is root, it is expected that access
>**                  will be granted even if permissions are explicitly
>**                  denied.
>**           Pass 2:
>**                  An attempt is made to chown the file to the provided
>**                  testuser and testgroup.
>**                  If the chown fails, a message is logged and the file
>**                  is skipped.
>**                  If the chown succeeds, a stat is performed to verify
>**                  the chown was effective. If the file owner and group
>**                  has not been modified, a message is logged and the file
>**                  is skipped.
>**                  Once the file is chowned, file permissions are verified
>**                  as the testuser/testgroup.
>**
>**           In all cases, links are skipped.  
>**
>**
>**  HISTORY:
>**     10/04     originated by Dan Jones (danjones at us.ibm.com)
>** A1  11/18/04  Kris Wilson (krisw at us.ibm.com)  If access is expected
>**               but denied, this is not a security problem, it is a
>**               problem if denial is expected but access allowed. So if
>**               pass is expected but fail received, this has been deemed
>**               OK for certification purposes.   
>**********************************************************************/
>#include <sys/types.h>
>#include <sys/dir.h>
>#include <sys/param.h>
>#include <sys/stat.h>
>#include <stdio.h>
>#include <unistd.h>
>#include <string.h>
>#include <pwd.h>
>#include <grp.h>
>#include <fcntl.h>
>#include <errno.h>
>
>extern int alphasort ();
>
>static int perms[] = {S_IRUSR, S_IWUSR, S_IXUSR,
>                      S_IRGRP, S_IWGRP, S_IXGRP,
>                      S_IROTH, S_IWOTH, S_IXOTH};
>static char *ptext[] = {"r", "w", "x", "r", "w", "x", "r", "w", "x"};
>
>int totalpass = 0;
>int totalfail = 0;
>uid_t uid_nobody = 65534;
>gid_t gid_nobody = 65533;
>
>int test = 0;
>static char *test_description[] = {"Check default permissions",
>				   "chown files to testuser/testgroup"};
>
>/*
> * Do not include . or .. in directory list.
> */ 
>int file_select (struct direct *entry)
>{
>  if ((strcmp (entry->d_name, ".") == 0) 
>      || (strcmp (entry->d_name, "..") == 0))
>    return (0);
>  else
>    return (1);
>}
>
>/*
> * Set euid, egid
> */
>void setids(uid_t uid, gid_t gid) {
>
>  int rc = 0;
>
>  if ((rc = setegid(gid)) == -1)
>    printf("\nERROR: unable to set gid. errno = %d\n", errno);
>  if ((rc = seteuid(uid)) == -1)
>    printf("\nERROR: unable to set uid. errno = %d\n", errno);
>
>  return;
>}
>
>/*
> * Check actual vs. expected access using open system call
> */
>void testaccess(char *pathname, int mode, int expected, char *outbuf) {
>
>  int testrc = 0;
>  int myerr = 0;
>
>  if (expected == -1) {
>    strcat(outbuf, "expected: fail  ");
>  } else {
>    strcat(outbuf, "expected: pass  ");
>  }
>
>  if ((testrc = open(pathname, mode)) == -1) {
>    myerr = errno;
>    strcat(outbuf, "actual: fail");
>  } else {
>    strcat(outbuf, "actual: pass");
>    close(testrc);
>  }
>
>  if (myerr == ENODEV) {
>    sprintf(&(outbuf[strlen(outbuf)]), "\tresult: SKIP : no device : %s\n", pathname);
>  } else if (myerr == EBUSY) {
>    sprintf(&(outbuf[strlen(outbuf)]), "\tresult: SKIP : device busy : %s\n", pathname);
>  } else if ((testrc == expected) || ((expected == 0) && (testrc != -1))) {
>    strcat(outbuf, "\tresult: PASS\n");
>    totalpass++;
>  } else {
>/* A1 OK if expected pass but got fail, but need to log so can manually check errno. */
>    if ((expected == 0) && (testrc == -1)) {
>        sprintf(&(outbuf[strlen(outbuf)]), "\tresult: FAIL/PASS : errno = %d : %s\n", errno, pathname);
>	totalpass++;
>    } else {
>        sprintf(&(outbuf[strlen(outbuf)]), "\tresult: FAIL : errno = %d : %s\n", errno, pathname);
>        totalfail++;
>    }
>  }
>
>  printf("%s", outbuf);
>
>  return;
>}
>
>/*
> * Test access for owner, group, other
> */
>void testall(struct stat *ostatbufp, char *pathname, uid_t uid, gid_t gid) {
>  
>  int i;
>  int rc = 0;
>  char outbuf[256];
>  struct passwd passwd;
>  struct passwd *passwdp;
>  struct group group;
>  struct group *groupp;
>  struct stat statbuf;
>  struct stat *statbufp = &statbuf;
>  char *pbuf;
>  char *gbuf;
>  
>  passwdp = (struct passwd *)malloc(sizeof(passwd));
>  groupp  = (struct group *)malloc(sizeof(group));
>  pbuf = (char *)malloc(4096);
>  gbuf = (char *)malloc(4096);
>  memset(pbuf, '\0', 4096);
>  memset(gbuf, '\0', 4096);
>
>  setids(0,0);
>  printf("\n%s\n", pathname);
>
>  // For test 1 we chown the file owner/group
>  if (test == 1) {
>    if ((rc = chown(pathname, uid, gid)) == -1) {
>      printf("ERROR: unable to chown %s to %d:%d\n", pathname, uid, gid);
>      goto EXIT;
>    }
>  }
>
>  // Start with clean buffers
>  memset(&statbuf, '\0', sizeof(statbuf));
>
>  // Get file stat info to determine actual owner and group
>  stat(pathname, &statbuf);
>
>  // If we successfully chown'd the file, but the owner hasn't changed
>  // log it and skip.
>  if ((test == 1) && ((statbufp->st_uid != uid) || (statbufp->st_gid != gid))) {
>    printf("INFO: chown success, but file owner did not change: %s\n", pathname);
>    goto EXIT;
>  }
>
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "MODE: ");
>  for (i = 0; i < sizeof(perms)/sizeof(int); i++) {
>    if (statbufp->st_mode & perms[i]) {
>      strcat(outbuf, ptext[i]);
>    } else {
>      strcat(outbuf, "-");
>    }
>  }
>  getpwuid_r(statbufp->st_uid, &passwd, pbuf, 4096, &passwdp);
>  getgrgid_r(statbufp->st_gid, &group, gbuf, 4096, &groupp);
>
>  sprintf(&(outbuf[strlen(outbuf)]), "  %s:%s\n", passwd.pw_name, group.gr_name);
>  printf("%s", outbuf);
>
>  // Check owner access for read/write
>  setids(statbufp->st_uid, gid_nobody);
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "Owner read\t");
>  // If we are root, we expect to succeed event
>  // without explicit permission.
>  if ((statbufp->st_mode & S_IRUSR) || (statbufp->st_uid == 0)) {
>    testaccess(pathname, O_RDONLY, 0, outbuf);
>  } else {
>    testaccess(pathname, O_RDONLY, -1, outbuf);
>  }
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "Owner write\t");
>  // If we are root, we expect to succeed event
>  // without explicit permission.
>  if ((statbufp->st_mode & S_IWUSR) || (statbufp->st_uid == 0)) {
>    testaccess(pathname, O_WRONLY, 0, outbuf);
>  } else {
>    testaccess(pathname, O_WRONLY, -1, outbuf);
>  }
>  
>  // Check group access for read/write
>  setids(0, 0);
>  setids(uid_nobody, statbufp->st_gid);
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "Group read\t");
>  if (statbufp->st_mode & S_IRGRP) {
>    testaccess(pathname, O_RDONLY, 0, outbuf);
>  } else {
>    testaccess(pathname, O_RDONLY, -1, outbuf);
>  }
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "Group write\t");
>  if (statbufp->st_mode & S_IWGRP) {
>    testaccess(pathname, O_WRONLY, 0, outbuf);
>  } else {
>    testaccess(pathname, O_WRONLY, -1, outbuf);
>  }
>  
>  // Check other access for read/write
>  setids(0, 0);
>  setids(uid_nobody, gid_nobody);
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "Other read\t");
>  if (statbufp->st_mode & S_IROTH) {
>    testaccess(pathname, O_RDONLY, 0, outbuf);
>  } else {
>    testaccess(pathname, O_RDONLY, -1, outbuf);
>  }
>  memset(outbuf, '\0', sizeof(outbuf));
>  strcat(outbuf, "Other write\t");
>  if (statbufp->st_mode & S_IWOTH) {
>    testaccess(pathname, O_WRONLY, 0, outbuf);
>  } else {
>    testaccess(pathname, O_WRONLY, -1, outbuf);
>  }
>
>  setids(0, 0);
>  
>  if (test == 1) {
>    chown(pathname, ostatbufp->st_uid, ostatbufp->st_gid);
>  }
>
>EXIT:  
>
>  return;
>}
>
>/*
> * Check access.
> *
> * This method check a file or recursively scan directories and verify
> * the file access modes are enforced.
> *
> */ 
>void check_access (char *pathname, uid_t uid, gid_t gid)
>{
>  int count = 0;
>  int i = 0;
>  int rc = 0;
>  int file_select ();
>  char entry[MAXPATHLEN];
>  struct dirent **entries;
>  struct stat statbuf;
>
>  // Start with clean buffers
>  memset(&statbuf, '\0', sizeof(statbuf));
>
>  // Get file stat info.
>  if ((rc = lstat(pathname, &statbuf)) == -1) {
>    printf("\nERROR: %s. Could not obtain file status. errno = %d\n", pathname, errno);
>    goto EXIT;
>  }
>
>  // If link, skip it.
>  if (S_ISLNK(statbuf.st_mode)) {
>    printf("Link: skipping %s\n", entry);
>    goto EXIT;
>  }
>
>  // If not a directory, check it and leave.
>  if (!(S_ISDIR(statbuf.st_mode))) {
>    testall(&statbuf, pathname, uid, gid);
>    goto EXIT;
>  } 
>
>  // If directory, recurse through all subdirectories, checking all files.
>  if ((count = scandir (pathname, &entries, file_select, alphasort)) == -1) {
>    printf("\nERROR: %s. Could not scandir. errno = %d\n", pathname, errno);
>    goto EXIT;
>  }
>  for (i = 0; i < count; i++) {
>
>    sprintf(entry, "%s/%s", pathname, entries[i]->d_name);
>    
>    // If link, skip it
>    // Else if directory, call check_access() recursively
>    if (entries[i]->d_type == DT_LNK) {
>      printf("Link: skipping %s\n", entry);
>      continue;
>    } else if (entries[i]->d_type == DT_DIR) {
>      check_access(entry, uid, gid);
>      continue;
>    }
>
>    // Clean the buffer
>    memset(&statbuf, '\0', sizeof(statbuf));
>
>    // Get file stat info.
>    if ((rc = lstat(entry, &statbuf)) == -1) {
>      printf("\nERROR: %s. Could not obtain file status. errno = %d\n", pathname, errno);
>      continue;
>    } 
>
>    // The directory entry doesn't always seem to have the
>    // right info. So we check again after the stat().
>    //
>    // If link, skip it
>    // Else if directory, call check_access() recursively
>    // Else check access
>    if (S_ISLNK(statbuf.st_mode)) {
>      printf("Link: (2) skipping %s\n", entry);
>      continue;
>    } else if (S_ISDIR(statbuf.st_mode)) {
>      check_access(entry, uid, gid);
>      continue;
>    } else {
>      testall(&statbuf, entry, uid, gid);
>      continue;
>    }
>  }
>
>EXIT:
>
>  return;
>}
>
>int main (int argc, char *argv[]) {
>
>  int i = 0;
>  struct passwd *pw;
>  struct group *gr;
>
>  if (argc != 4) {
>    printf("usage: checkchown <directory> <testuser> <testgroup>\n");
>    goto EXIT;
>  }
>
>  if ((pw = getpwnam(argv[2])) == NULL) {
>    printf("ERROR: invalid username %s\n", argv[2]);
>    goto EXIT;
>  }
>  if ((gr = getgrnam(argv[3])) == NULL) {
>    printf("ERROR: invalid group %s\n", argv[3]);
>    goto EXIT;
>  }
>
>  for (i = 0; i < 2; i++) {
>    totalpass = 0;
>    totalfail = 0;
>    test = i;
>    printf("Test: %s\n\n", test_description[i]);
>    check_access(argv[1], pw->pw_uid, gr->gr_gid);
>    printf("\nPASS = %d, FAIL = %d\n\n", totalpass, totalfail);
>  }
>
> EXIT:
>
>  return (0);
>}
>
>
>  
>
Linda,
    Is this test out of the additions to the LTP test suite for audit?

Thanks,
Jeff




More information about the Linux-audit mailing list