Bug#318826: libpam-umask encounters a Segmentation fault - preventing login
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
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
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) + +