comparison svr-chansession.c @ 1510:eb4c7052f51d coverity

merge coverity up to date
author Matt Johnston <matt@ucc.asn.au>
date Sat, 17 Feb 2018 11:29:17 +0800
parents 47f36d8565cf
children 79eef94ccea9
comparison
equal deleted inserted replaced
1509:3520d7c25363 1510:eb4c7052f51d
78 struct ChanSess *chansess = (struct ChanSess*)channel->typedata; 78 struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
79 TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid)) 79 TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid))
80 return chansess->exit.exitpid != -1; 80 return chansess->exit.exitpid != -1;
81 } 81 }
82 82
83 void svr_chansess_checksignal(void) {
84 int status;
85 pid_t pid;
86
87 if (!ses.channel_signal_pending) {
88 return;
89 }
90
91 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
92 unsigned int i;
93 struct exitinfo *ex = NULL;
94 TRACE(("sigchld handler: pid %d", pid))
95
96 ex = NULL;
97 /* find the corresponding chansess */
98 for (i = 0; i < svr_ses.childpidsize; i++) {
99 if (svr_ses.childpids[i].pid == pid) {
100 TRACE(("found match session"));
101 ex = &svr_ses.childpids[i].chansess->exit;
102 break;
103 }
104 }
105
106 /* If the pid wasn't matched, then we might have hit the race mentioned
107 * above. So we just store the info for the parent to deal with */
108 if (ex == NULL) {
109 TRACE(("using lastexit"));
110 ex = &svr_ses.lastexit;
111 }
112
113 ex->exitpid = pid;
114 if (WIFEXITED(status)) {
115 ex->exitstatus = WEXITSTATUS(status);
116 }
117 if (WIFSIGNALED(status)) {
118 ex->exitsignal = WTERMSIG(status);
119 #if !defined(AIX) && defined(WCOREDUMP)
120 ex->exitcore = WCOREDUMP(status);
121 #else
122 ex->exitcore = 0;
123 #endif
124 } else {
125 /* we use this to determine how pid exited */
126 ex->exitsignal = -1;
127 }
128
129 }
130 }
131
83 /* Handler for childs exiting, store the state for return to the client */ 132 /* Handler for childs exiting, store the state for return to the client */
84 133
85 /* There's a particular race we have to watch out for: if the forked child 134 /* There's a particular race we have to watch out for: if the forked child
86 * executes, exits, and this signal-handler is called, all before the parent 135 * executes, exits, and this signal-handler is called, all before the parent
87 * gets to run, then the childpids[] array won't have the pid in it. Hence we 136 * gets to run, then the childpids[] array won't have the pid in it. Hence we
88 * use the svr_ses.lastexit struct to hold the exit, which is then compared by 137 * use the svr_ses.lastexit struct to hold the exit, which is then compared by
89 * the parent when it runs. This work correctly at least in the case of a 138 * the parent when it runs. This work correctly at least in the case of a
90 * single shell spawned (ie the usual case) */ 139 * single shell spawned (ie the usual case) */
91 static void sesssigchild_handler(int UNUSED(dummy)) { 140 static void sesssigchild_handler(int UNUSED(dummy)) {
92
93 int status;
94 pid_t pid;
95 unsigned int i;
96 struct sigaction sa_chld; 141 struct sigaction sa_chld;
97 struct exitinfo *exit = NULL;
98 142
99 const int saved_errno = errno; 143 const int saved_errno = errno;
100 144
101 /* Make channel handling code look for closed channels */
102 ses.channel_signal_pending = 1;
103
104 TRACE(("enter sigchld handler")) 145 TRACE(("enter sigchld handler"))
105 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 146
106 TRACE(("sigchld handler: pid %d", pid)) 147 /* Make sure that the main select() loop wakes up */
107 148 while (1) {
108 exit = NULL; 149 /* isserver is just a random byte to write. We can't do anything
109 /* find the corresponding chansess */ 150 about an error so should just ignore it */
110 for (i = 0; i < svr_ses.childpidsize; i++) { 151 if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
111 if (svr_ses.childpids[i].pid == pid) { 152 || errno != EINTR) {
112 TRACE(("found match session")); 153 break;
113 exit = &svr_ses.childpids[i].chansess->exit;
114 break;
115 }
116 }
117
118 /* If the pid wasn't matched, then we might have hit the race mentioned
119 * above. So we just store the info for the parent to deal with */
120 if (exit == NULL) {
121 TRACE(("using lastexit"));
122 exit = &svr_ses.lastexit;
123 }
124
125 exit->exitpid = pid;
126 if (WIFEXITED(status)) {
127 exit->exitstatus = WEXITSTATUS(status);
128 }
129 if (WIFSIGNALED(status)) {
130 exit->exitsignal = WTERMSIG(status);
131 #if !defined(AIX) && defined(WCOREDUMP)
132 exit->exitcore = WCOREDUMP(status);
133 #else
134 exit->exitcore = 0;
135 #endif
136 } else {
137 /* we use this to determine how pid exited */
138 exit->exitsignal = -1;
139 }
140
141 /* Make sure that the main select() loop wakes up */
142 while (1) {
143 /* isserver is just a random byte to write. We can't do anything
144 about an error so should just ignore it */
145 if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1
146 || errno != EINTR) {
147 break;
148 }
149 } 154 }
150 } 155 }
151 156
152 sa_chld.sa_handler = sesssigchild_handler; 157 sa_chld.sa_handler = sesssigchild_handler;
153 sa_chld.sa_flags = SA_NOCLDSTOP; 158 sa_chld.sa_flags = SA_NOCLDSTOP;
656 /* TODO - send error - too long ? */ 661 /* TODO - send error - too long ? */
657 return DROPBEAR_FAILURE; 662 return DROPBEAR_FAILURE;
658 } 663 }
659 } 664 }
660 if (issubsys) { 665 if (issubsys) {
661 #ifdef SFTPSERVER_PATH 666 #if DROPBEAR_SFTPSERVER
662 if ((cmdlen == 4) && strncmp(chansess->cmd, "sftp", 4) == 0) { 667 if ((cmdlen == 4) && strncmp(chansess->cmd, "sftp", 4) == 0) {
663 m_free(chansess->cmd); 668 m_free(chansess->cmd);
664 chansess->cmd = m_strdup(SFTPSERVER_PATH); 669 chansess->cmd = m_strdup(SFTPSERVER_PATH);
665 } else 670 } else
666 #endif 671 #endif
680 /* take public key option 'command' into account */ 685 /* take public key option 'command' into account */
681 svr_pubkey_set_forced_command(chansess); 686 svr_pubkey_set_forced_command(chansess);
682 } 687 }
683 688
684 689
685 #ifdef LOG_COMMANDS 690 #if LOG_COMMANDS
686 if (chansess->cmd) { 691 if (chansess->cmd) {
687 dropbear_log(LOG_INFO, "User %s executing '%s'", 692 dropbear_log(LOG_INFO, "User %s executing '%s'",
688 ses.authstate.pw_name, chansess->cmd); 693 ses.authstate.pw_name, chansess->cmd);
689 } else { 694 } else {
690 dropbear_log(LOG_INFO, "User %s executing login shell", 695 dropbear_log(LOG_INFO, "User %s executing login shell",
767 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ 772 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
768 static int ptycommand(struct Channel *channel, struct ChanSess *chansess) { 773 static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
769 774
770 pid_t pid; 775 pid_t pid;
771 struct logininfo *li = NULL; 776 struct logininfo *li = NULL;
772 #ifdef DO_MOTD 777 #if DO_MOTD
773 buffer * motdbuf = NULL; 778 buffer * motdbuf = NULL;
774 int len; 779 int len;
775 struct stat sb; 780 struct stat sb;
776 char *hushpath = NULL; 781 char *hushpath = NULL;
777 #endif 782 #endif
819 * terminal used for stdout with the dup2 above */ 824 * terminal used for stdout with the dup2 above */
820 li = chansess_login_alloc(chansess); 825 li = chansess_login_alloc(chansess);
821 login_login(li); 826 login_login(li);
822 login_free_entry(li); 827 login_free_entry(li);
823 828
824 #ifdef DO_MOTD 829 #if DO_MOTD
825 if (svr_opts.domotd && !chansess->cmd) { 830 if (svr_opts.domotd && !chansess->cmd) {
826 /* don't show the motd if ~/.hushlogin exists */ 831 /* don't show the motd if ~/.hushlogin exists */
827 832
828 /* 12 == strlen("/.hushlogin\0") */ 833 /* 12 == strlen("/.hushlogin\0") */
829 len = strlen(ses.authstate.pw_dir) + 12; 834 len = strlen(ses.authstate.pw_dir) + 12;
897 } 902 }
898 903
899 /* Clean up, drop to user privileges, set up the environment and execute 904 /* Clean up, drop to user privileges, set up the environment and execute
900 * the command/shell. This function does not return. */ 905 * the command/shell. This function does not return. */
901 static void execchild(const void *user_data) { 906 static void execchild(const void *user_data) {
902 struct ChanSess *chansess = user_data; 907 const struct ChanSess *chansess = user_data;
903 char *usershell = NULL; 908 char *usershell = NULL;
904 909
905 /* with uClinux we'll have vfork()ed, so don't want to overwrite the 910 /* with uClinux we'll have vfork()ed, so don't want to overwrite the
906 * hostkey. can't think of a workaround to clear it */ 911 * hostkey. can't think of a workaround to clear it */
907 #if !DROPBEAR_VFORK 912 #if !DROPBEAR_VFORK