Bug#318826: libpam-umask encounters a Segmentation fault - preventing login

2005-07-18 Thread Michael Berg
Package: libpam-umask
Version: 0.02
Severity: grave
Justification: renders package unusable

The latest libpam-umask (0.02) encounters a SIGSEGV (Segmentation fault)
that prevents all uses from logging in through any path that references
pam_umask.so in the PAM configuration.

This even effects optional entries in PAM configurations since
pam_umask.so seg-faults.

I had the following line in /etc/pam.d/common-session
sessionoptionalpam_umask.so umask=0077

Commenting out this line allows users to log in again.


Below are ltrace and gdb output for the getty process when pam_umask
is enabled on the system.

Running getty through ltrace, and then attempting to log in produced
# ltrace /sbin/getty 38400 tty8
...
pam_start(0x804f1c9, 0xbfe1a2d0, 0x804f088, 0x8051618, 0)= 0
pam_set_item(0x9242228, 4, 0x804ff87, 0x8051618, 0)  = 0
pam_set_item(0x9242228, 3, 0xbfe182d0, 0x8051618, 0) = 0
pam_fail_delay(0x9242228, 0x2dc6c0, 0xbfe182d0, 0x8051618, 0) = 0
gethostname(server, 256)   = 0
snprintf(server login: , 256, %s login: , server)  = 14
pam_set_item(0x9242228, 9, 0xbfe17e50, 0xbfe17f50, 0)= 0
pam_get_item(0x9242228, 2, 0xbfe17e48, 0xbfe17f50, 0)= 0
pam_fail_delay(0x9242228, 0x2dc6c0, 0xbfe17e48, 0xbfe17f50, 0) = 0
pam_authenticate(0x9242228, 0, 0xbfe17e48, 0xbfe17f50, 0 unfinished ...
misc_conv(1, 0xbfe17d1c, 0xbfe17d28, 0, 0xb7f0a280)  = 0
... pam_authenticate resumed ) = 0
pam_get_item(0x9242228, 2, 0xbfe17e48, 0xbfe17f50, 0)= 0
getpwnam(michael)  = 0x4114c0b8
strcmp(MAIL_CHECK_ENAB, FAILLOG_ENAB)= 1
strcmp(ERASECHAR, FAILLOG_ENAB)  = -1
strcmp(HUSHLOGIN_FILE, FAILLOG_ENAB) = 1
strcmp(FTMP_FILE, FAILLOG_ENAB)  = 1
strcmp(FAIL_DELAY, FAILLOG_ENAB) = 1
strcmp(FAILLOG_ENAB, FAILLOG_ENAB)   = 0
strcasecmp(yes, yes) = 0
open64(/var/log/faillog, 2, 0145)  = 7
lseek64(7, 24, 0, 0, 0x41021158) = 24
read(7, , 24)  = 24
lseek64(7, 24, 0, 0, 0)  = 24
write(7, , 24) = 24
close(7) = 0
alarm(0) = 58
pam_acct_mgmt(0x9242228, 0, 0, 0xbfe17f50, 0)= 0
pam_get_item(0x9242228, 2, 0xbfe17e48, 0xbfe17f50, 0)= 0
setpwent()   = void
getpwnam(michael)  = 0x4114c0b8
setgid(1)= 0
initgroups(0x9249e5a, 1, 0x4114c0b8, 0x4114c0b8, 0x4114c0b8) = 0
pam_setcred(0x9242228, 2, 0xbfe17e48, 0xbfe17f50, 0) = 0
strcmp(MAIL_CHECK_ENAB, HUSHLOGIN_FILE)  = 1
strcmp(ERASECHAR, HUSHLOGIN_FILE)= -1
strcmp(HUSHLOGIN_FILE, HUSHLOGIN_FILE)   = 0
snprintf(/home/michael/.hushlogin, 8192, %s/%s, /home/michael, 
.hushlogin) = 24
access(/home/michael/.hushlogin, 0)= -1
pam_open_session(0x9242228, 0, 0xbfe17e48, 0xbfe17f50, 0 unfinished ...
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++


Running getty through strace produced no interesting information.


Running getty through gdb, I obtained the following backtrace
(long runs of 0x are replaced with ...)

Program received signal SIGSEGV, Segmentation fault.
0x00126abe in ?? ()
(gdb) bt
#0  0x00126abe in ?? ()
#1  0x4114b8a8 in main_arena () from /lib/tls/i686/cmov/libc.so.6
#2  0x08048f00 in ?? ()
#3  0x in ?? ()
#4  0x4114c0b8 in buffer_size.0 () from /lib/tls/i686/cmov/libc.so.6
#5  0x00802b60 in ?? ()
#6  0x08143f80 in ?? ()
#7  0x0813f228 in ?? ()
#8  0xbff1d0d8 in ?? ()
#9  0x007fda1c in ?? ()
#10 0x0813f228 in ?? ()
#11 0x in ?? ()
#12 0x0001 in ?? ()
#13 0x08143c10 in ?? ()
#14 0xb7f1f19c in ?? ()
#15 0x0001 in ?? ()
#16 0x in ?? ()
#17 0x in ?? ()
#18 0x in ?? ()
#19 0x in ?? ()
#20 0x0006 in ?? ()
#21 0x0020 in ?? ()
#22 0xffe0 in ?? ()
#23 0x08051178 in ?? ()
#24 0x003c in ?? ()
#25 0x00802b60 in ?? ()
#26 0x in ?? ()
#27 0x in ?? ()
#28 0xbff1d0f8 in ?? ()
#29 0x007ff9fb in ?? ()
#30 0x0813f228 in ?? ()
#31 0x in ?? ()
#32 0x0004 in ?? ()
#33 0xffe0 in ?? ()
#34 0x0813f228 in ?? ()
#35 0x4114c0b8 in buffer_size.0 () from /lib/tls/i686/cmov/libc.so.6
#36 0xbff1f5f8 in ?? ()
#37 0x0804addb in ?? ()
#38 0x0813f228 in ?? ()
#39 0x in ?? ()
#40 0xbff1d138 in ?? ()
#41 0xbff1d240 in ?? ()
#42 0x in ?? ()
#43 0x in ?? ()
#44 0x in ?? ()
#45 0x in ?? ()
#46 0x08146e58 in ?? ()

Bug#318826: libpam-umask encounters a Segmentation fault - preventing login

2005-07-18 Thread dean gaudet
On Sun, 17 Jul 2005, Michael Berg wrote:

 The latest libpam-umask (0.02) encounters a SIGSEGV (Segmentation fault)

this is because of some unfortunate code that i don't even think should be 
in the module... it's a result of the per-user umask support.  it 
segfaults for any user which does *not* have a ~/.pam_umask file... but 
it's even worse...

there's a pointer manipulation error causing the segfault -- the user 
parm passed to pam_get_item is a pointer to random garbage which 
pam_get_item then fills in...

there's an off-by-1 in the umask_file_path allocation...

it logs far too much... and per-user support really should be optional.

i'm working on a patch...

-dean


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]



Bug#318826: libpam-umask encounters a Segmentation fault - preventing login

2005-07-18 Thread dean gaudet
here's my patch.

sorry it's large because i think that per-user umask should be optional, 
so i've done most of the work to make that happen... now you have to 
specify user as an argument to pam_umask.so... as it happens it has to 
be the first argument, because arguments are processed left-to-right.

in theory i really think it should be user=~/.pam_umask or somethign like 
that (so that different pam configurations can use different umasks) but 
really i think this is total feeping creaturism.  personally i'd do 
without the per-user stuff entirely... but at least this patch makes it 
stop segfaulting.

-dean

diff -ru pam-umask-0.02/README pam-umask-0.02.dg1/README
--- pam-umask-0.02/README   2005-07-17 06:26:31.0 -0700
+++ pam-umask-0.02.dg1/README   2005-07-18 16:02:36.214696259 -0700
@@ -12,14 +12,22 @@
 
 sessionoptional pam_umask.so umask=002
 
-to the services where you want to set the umask to 002
+to the services where you want to set the umask to 002.  (For example
+in /etc/pam.d/common-session.)
 
 Note that using optional instead of required will allow users to
 login even if pam_umask fails to parse the umask line.  Using
 required will deny login if an error occurs while setting the umask,
 which is clearly a non-desireable situation.
 
-The module also supports per-user umasks.  If a user has a .pam_umask
-in his home directory, the contents will be used to set the umask.
-Note that strtol is used for parsing, so making sure to have a leading
-zero (like 022 or 002) is recommended.
+The module also supports per-user umasks.  To enable per-user umasks
+use a line like so:
+
+sessionoptional pam_umask.so user umask=002
+
+In this case, if a user has a .pam_umask in his home directory, the
+contents will be used to set the umask.  Note that strtol is used
+for parsing, so making sure to have a leading zero (like 022 or 002)
+is recommended.  Otherwise the umask=002 argument will be used.
+
+(Note that the ordering of arguments is important.)
diff -ru pam-umask-0.02/pam_umask.c pam-umask-0.02.dg1/pam_umask.c
--- pam-umask-0.02/pam_umask.c  2005-07-17 06:34:53.0 -0700
+++ pam-umask-0.02.dg1/pam_umask.c  2005-07-18 15:56:04.955805118 -0700
@@ -48,54 +48,17 @@
 PAM_EXTERN
 int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, 
 const char **argv) {
-  const char **user;
-  int ret;
-  struct passwd *puser;
-  FILE *umask_file;
-  char *umask_file_path, *user_umask;
   mode_t um;
+  int i;
 
-  ret = pam_get_item(pamh, PAM_USER, user);
-  if (ret != PAM_SUCCESS) {
-_log_err(LOG_ERR, Can't get user);
+  if (argc == 0) {
+_log_err(LOG_ERR, at least one of \umask=NNN\ or \user\ must be 
supplied);
 return PAM_SESSION_ERR;
   }
 
-  puser = getpwnam(*user);
-  if (!puser) {
-_log_err(LOG_ERR, User %s not found using getpwent, *user);
-return PAM_SESSION_ERR;
-  }
-  _log_err(LOG_ERR, User is %s, *user);
-
-  umask_file_path = xmalloc(strlen(puser-pw_dir) + 
-strlen(PAM_UMASK_FILE_NAME) +
-1);
-  sprintf(umask_file_path, %s/%s, puser-pw_dir, PAM_UMASK_FILE_NAME);
-
-  umask_file = fopen(umask_file_path, r);
-
-  if (umask_file != NULL) {
-user_umask = freadline(umask_file);
-um = strtol(user_umask, NULL, 0);
-if (um == LONG_MIN || um == LONG_MAX) {
-  _log_err(LOG_ERR, illegal umask specified for user: %s, 
puser-pw_name);
-  return PAM_SESSION_ERR;
-}
-fclose(umask_file);
-umask(um);
-return PAM_SUCCESS;
-  }
-
-  _log_err(LOG_ERR, .pam file not found, *user);
-
-
-  /* Ok, either no file, unreadable or something else. Ignore and go on with
- the system umask. */
-
-  if (argc--  0) {
-if (strncmp(argv[argc], umask=, 6) == 0) {
-  um = strtol((argv[argc])+6, NULL, 0);
+  for (i = 0; i  argc; ++i) {
+if (strncmp(argv[i], umask=, 6) == 0) {
+  um = strtol((argv[i])+6, NULL, 0);
   if (um == LONG_MIN || um == LONG_MAX) {
 _log_err(LOG_ERR, illegal umask specified);
 return PAM_SESSION_ERR;
@@ -103,8 +66,57 @@
   umask(um);
   return PAM_SUCCESS;
 }
+// TODO:  this really should be user=~/.pam_umask ... so that different
+// pam config files could specify different per-user umask files... but
+// damn this is really feeping creaturism.
+else if (strcmp(argv[i], user) == 0) {
+  const void *v_user;
+  const char *user;
+  int ret;
+  struct passwd *puser;
+  FILE *umask_file;
+  char *umask_file_path, *user_umask;
+
+  ret = pam_get_item(pamh, PAM_USER, v_user);
+  if (ret != PAM_SUCCESS) {
+   _log_err(LOG_ERR, Can't get user);
+   return PAM_SESSION_ERR;
+  }
+  user = v_user;
+
+  puser = getpwnam(user);
+  if (!puser) {
+   _log_err(LOG_ERR, User %s not found using getpwent, user);
+   return PAM_SESSION_ERR;
+  }
+
+  umask_file_path = xmalloc(strlen(puser-pw_dir) + 
+