ruby-lsapi 5.8 → 5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/lsapi/lsapilib.c CHANGED
@@ -158,6 +158,9 @@ LSAPI_Request g_req =
158
158
  static char s_secret[24];
159
159
 
160
160
  static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
161
+ static LSAPI_Fork_Hook_pf s_fork_before = NULL;
162
+ static LSAPI_Fork_Hook_pf s_fork_after_parent = NULL;
163
+ static LSAPI_Fork_Hook_pf s_fork_after_child = NULL;
161
164
 
162
165
  void Flush_RespBuf_r( LSAPI_Request * pReq );
163
166
  static int lsapi_reopen_stderr(const char *p);
@@ -547,12 +550,21 @@ static inline int allocateBuf( LSAPI_Request * pReq, int size )
547
550
 
548
551
  static int allocateIovec( LSAPI_Request * pReq, int n )
549
552
  {
553
+ ptrdiff_t toWriteOff = 0;
554
+ ptrdiff_t curOff = 0;
555
+ if (n <= 0)
556
+ return -1;
557
+ if (pReq->m_pIovec)
558
+ {
559
+ toWriteOff = pReq->m_pIovecToWrite - pReq->m_pIovec;
560
+ curOff = pReq->m_pIovecCur - pReq->m_pIovec;
561
+ }
550
562
  struct iovec * p = (struct iovec *)realloc(
551
563
  pReq->m_pIovec, sizeof(struct iovec) * n );
552
564
  if ( !p )
553
565
  return -1;
554
- pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
555
- pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
566
+ pReq->m_pIovecToWrite = p + toWriteOff;
567
+ pReq->m_pIovecCur = p + curOff;
556
568
  pReq->m_pIovec = p;
557
569
  pReq->m_pIovecEnd = p + n;
558
570
  return 0;
@@ -561,10 +573,15 @@ static int allocateIovec( LSAPI_Request * pReq, int n )
561
573
 
562
574
  static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
563
575
  {
576
+ ptrdiff_t posOff = 0;
577
+ if (size <= 0)
578
+ return -1;
579
+ if (pReq->m_pRespHeaderBuf)
580
+ posOff = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
564
581
  char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
565
582
  if ( !p )
566
583
  return -1;
567
- pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
584
+ pReq->m_pRespHeaderBufPos = p + posOff;
568
585
  pReq->m_pRespHeaderBuf = p;
569
586
  pReq->m_pRespHeaderBufEnd = p + size;
570
587
  return 0;
@@ -617,8 +634,8 @@ static inline int isPipe( int fd )
617
634
  {
618
635
  char achPeer[128];
619
636
  socklen_t len = 128;
620
- if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
621
- ( errno == ENOTCONN ))
637
+ if ((getpeername(fd, (struct sockaddr *)achPeer, &len) != 0 )
638
+ && (errno == ENOTCONN || errno == ENOTSOCK))
622
639
  return 0;
623
640
  else
624
641
  return 1;
@@ -628,23 +645,31 @@ static inline int isPipe( int fd )
628
645
  static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
629
646
  char **pBegin, char * pEnd )
630
647
  {
631
- struct LSAPI_key_value_pair * pEnvEnd;
632
- int keyLen = 0, valLen = 0;
633
- if ( count > 8192 )
648
+ int i;
649
+ int keyLen = 0, valLen = 0;
650
+ size_t remaining;
651
+
652
+ if (count < 0 || count > 8192 || !pBegin || !*pBegin
653
+ || !pEnd || *pBegin > pEnd || (count && !pEnvList))
634
654
  return -1;
635
- pEnvEnd = pEnvList + count;
636
- while( pEnvList != pEnvEnd )
655
+ for (i = 0; i < count; ++i, ++pEnvList)
637
656
  {
638
- if ( pEnd - *pBegin < 4 )
657
+ remaining = (size_t)(pEnd - *pBegin);
658
+ if (remaining < 4)
639
659
  return -1;
640
660
  keyLen = *((unsigned char *)((*pBegin)++));
641
661
  keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
642
662
  valLen = *((unsigned char *)((*pBegin)++));
643
663
  valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
644
- if ( *pBegin + keyLen + valLen > pEnd )
645
- return -1;
646
664
  if (( !keyLen )||( !valLen ))
647
665
  return -1;
666
+ remaining = (size_t)(pEnd - *pBegin);
667
+ if ((size_t)keyLen > remaining
668
+ || (size_t)valLen > remaining - (size_t)keyLen)
669
+ return -1;
670
+ if ((*pBegin)[keyLen - 1] != '\0'
671
+ || (*pBegin)[keyLen + valLen - 1] != '\0')
672
+ return -1;
648
673
 
649
674
  pEnvList->pKey = *pBegin;
650
675
  *pBegin += keyLen;
@@ -653,9 +678,9 @@ static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
653
678
 
654
679
  pEnvList->keyLen = keyLen - 1;
655
680
  pEnvList->valLen = valLen - 1;
656
- ++pEnvList;
657
681
  }
658
- if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
682
+ if ((size_t)(pEnd - *pBegin) < 4
683
+ || memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
659
684
  return -1;
660
685
  *pBegin += 4;
661
686
  return 0;
@@ -694,7 +719,7 @@ static inline void fixEndian( LSAPI_Request * pReq )
694
719
  static void fixHeaderIndexEndian( LSAPI_Request * pReq )
695
720
  {
696
721
  int i;
697
- for( i = 0; i < H_TRANSFER_ENCODING; ++i )
722
+ for( i = 0; i <= H_TRANSFER_ENCODING; ++i )
698
723
  {
699
724
  if ( pReq->m_pHeaderIndex->m_headerOff[i] )
700
725
  {
@@ -727,13 +752,16 @@ static int validateHeaders( LSAPI_Request * pReq )
727
752
  {
728
753
  int totalLen = pReq->m_pHeader->m_httpHeaderLen;
729
754
  int i;
730
- for(i = 0; i < H_TRANSFER_ENCODING; ++i)
755
+ if (totalLen < 0)
756
+ return -1;
757
+ for(i = 0; i <= H_TRANSFER_ENCODING; ++i)
731
758
  {
732
759
  if ( pReq->m_pHeaderIndex->m_headerOff[i] )
733
760
  {
734
- if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
735
- || pReq->m_pHeaderIndex->m_headerLen[i]
736
- + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
761
+ int off = pReq->m_pHeaderIndex->m_headerOff[i];
762
+ int len = pReq->m_pHeaderIndex->m_headerLen[i];
763
+ if (off < 0 || off >= totalLen || len < 0
764
+ || len >= totalLen - off)
737
765
  return -1;
738
766
  }
739
767
  }
@@ -744,10 +772,12 @@ static int validateHeaders( LSAPI_Request * pReq )
744
772
  pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
745
773
  while( pCur < pEnd )
746
774
  {
747
- if (pCur->nameOff > totalLen
748
- || pCur->nameOff + pCur->nameLen > totalLen
749
- || pCur->valueOff > totalLen
750
- || pCur->valueOff + pCur->valueLen > totalLen)
775
+ if (pCur->nameOff < 0 || pCur->nameLen <= 0
776
+ || pCur->nameOff >= totalLen
777
+ || pCur->nameLen >= totalLen - pCur->nameOff
778
+ || pCur->valueOff < 0 || pCur->valueLen < 0
779
+ || pCur->valueOff >= totalLen
780
+ || pCur->valueLen >= totalLen - pCur->valueOff)
751
781
  return -1;
752
782
  ++pCur;
753
783
  }
@@ -780,29 +810,32 @@ static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
780
810
  static int lsapi_load_lve_lib(void)
781
811
  {
782
812
  s_liblve = dlopen("liblve.so.0", RTLD_NOW | RTLD_GLOBAL);
783
- if (s_liblve)
813
+ if (!s_liblve)
784
814
  {
785
- fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
786
- if (dlerror() == NULL)
815
+ lsapi_log("LSAPI: configured LVE library could not be loaded: %s\n",
816
+ dlerror());
817
+ return -1;
818
+ }
819
+
820
+ fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
821
+ if (fp_lve_is_available && !(*fp_lve_is_available)())
822
+ {
823
+ uid_t uid = getuid();
824
+ if (uid)
787
825
  {
788
- if ( !(*fp_lve_is_available)() )
826
+ if (setreuid(s_uid, uid) == 0)
789
827
  {
790
- int uid = getuid();
791
- if ( uid )
792
- {
793
- if (setreuid( s_uid, uid )) {};
794
- if ( !(*fp_lve_is_available)() )
795
- s_enable_lve = 0;
796
- if (setreuid( uid, s_uid )) {};
797
- }
828
+ int available = (*fp_lve_is_available)();
829
+ if (setreuid(uid, s_uid) == -1)
830
+ return -1;
831
+ if (available)
832
+ return 0;
798
833
  }
799
834
  }
835
+ lsapi_log("LSAPI: configured LVE support is unavailable\n");
836
+ return -1;
800
837
  }
801
- else
802
- {
803
- s_enable_lve = LSAPI_LVE_DISABLED;
804
- }
805
- return (s_liblve)? 0 : -1;
838
+ return 0;
806
839
  }
807
840
 
808
841
 
@@ -817,11 +850,23 @@ static int init_lve_ex(void)
817
850
  fp_lve_leave = dlsym(s_liblve, "lve_leave");
818
851
  if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
819
852
  fp_lve_jail = dlsym(s_liblve, "jail" );
853
+ if (!fp_lve_instance_init || !fp_lve_enter)
854
+ {
855
+ lsapi_log("LSAPI: required LVE symbols are unavailable\n");
856
+ return -1;
857
+ }
858
+ if (s_enable_lve >= LSAPI_CAGEFS_ENABLED && !fp_lve_jail)
859
+ lsapi_log("LSAPI: CageFS jail symbol is unavailable; "
860
+ "continuing with LVE limits only\n");
820
861
 
821
862
  if ( s_lve == NULL )
822
863
  {
823
864
  rc = (*fp_lve_instance_init)(NULL);
865
+ if (rc <= 0 || rc > 1024 * 1024)
866
+ return -1;
824
867
  s_lve = malloc(rc);
868
+ if (!s_lve)
869
+ return -1;
825
870
  }
826
871
  rc = (*fp_lve_instance_init)(s_lve);
827
872
  if (rc != 0)
@@ -842,7 +887,16 @@ static int init_lve_ex(void)
842
887
  static int readSecret( const char * pSecretFile )
843
888
  {
844
889
  struct stat st;
845
- int fd = open( pSecretFile, O_RDONLY , 0600 );
890
+ size_t readLen = 0;
891
+ ssize_t len;
892
+ int flags = O_RDONLY;
893
+ #ifdef O_CLOEXEC
894
+ flags |= O_CLOEXEC;
895
+ #endif
896
+ #ifdef O_NOFOLLOW
897
+ flags |= O_NOFOLLOW;
898
+ #endif
899
+ int fd = open(pSecretFile, flags);
846
900
  if ( fd == -1 )
847
901
  {
848
902
  lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
@@ -854,25 +908,34 @@ static int readSecret( const char * pSecretFile )
854
908
  close( fd );
855
909
  return -1;
856
910
  }
857
- /*
858
- if ( st.st_uid != s_uid )
911
+ if (!S_ISREG(st.st_mode) || st.st_uid != s_uid)
859
912
  {
860
- lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
913
+ lsapi_log("LSAPI: secret file type or owner check failure: %s!\n",
914
+ pSecretFile);
861
915
  close( fd );
862
916
  return -1;
863
917
  }
864
- */
865
918
  if ( st.st_mode & 0077 )
866
919
  {
867
920
  lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
868
921
  close( fd );
869
922
  return -1;
870
923
  }
871
- if ( read( fd, s_secret, 16 ) < 16 )
924
+ while (readLen < 16)
872
925
  {
873
- lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
874
- close( fd );
875
- return -1;
926
+ len = read(fd, s_secret + readLen, 16 - readLen);
927
+ if (len > 0)
928
+ readLen += len;
929
+ else if (len == -1 && errno == EINTR)
930
+ continue;
931
+ else
932
+ {
933
+ lsapi_log("LSAPI: failed to read secret from secret file: %s\n",
934
+ pSecretFile);
935
+ memset(s_secret, 0, sizeof(s_secret));
936
+ close(fd);
937
+ return -1;
938
+ }
876
939
  }
877
940
  close( fd );
878
941
  return 0;
@@ -978,12 +1041,9 @@ static int lsapi_initLVE(void)
978
1041
  }
979
1042
  if ( s_enable_lve && !s_uid )
980
1043
  {
981
- lsapi_load_lve_lib();
982
- if ( s_enable_lve )
983
- {
984
- return init_lve_ex();
985
- }
986
-
1044
+ if (lsapi_load_lve_lib() == -1)
1045
+ return -1;
1046
+ return init_lve_ex();
987
1047
  }
988
1048
  return 0;
989
1049
  }
@@ -1014,10 +1074,12 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
1014
1074
  }
1015
1075
  }
1016
1076
  #endif
1017
- //if ( !uid || !gid ) //do not allow root
1018
- //{
1019
- // return -1;
1020
- //}
1077
+ if (!uid || !gid)
1078
+ {
1079
+ errno = EPERM;
1080
+ LSAPI_perror_r(pReq, "LSAPI: refusing root UID or GID", NULL);
1081
+ return -1;
1082
+ }
1021
1083
 
1022
1084
  #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
1023
1085
  || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
@@ -1025,12 +1087,6 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
1025
1087
  lsapi_enable_core_dump();
1026
1088
  #endif
1027
1089
 
1028
- rv = setgid(gid);
1029
- if (rv == -1)
1030
- {
1031
- LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
1032
- return -1;
1033
- }
1034
1090
  if ( pw && (pw->pw_gid == gid ))
1035
1091
  {
1036
1092
  rv = initgroups( pw->pw_name, gid );
@@ -1046,8 +1102,15 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
1046
1102
  if (rv == -1)
1047
1103
  {
1048
1104
  LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
1105
+ return -1;
1049
1106
  }
1050
1107
  }
1108
+ rv = setgid(gid);
1109
+ if (rv == -1)
1110
+ {
1111
+ LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
1112
+ return -1;
1113
+ }
1051
1114
  if ( pChroot )
1052
1115
  {
1053
1116
  rv = chroot( pChroot );
@@ -1056,6 +1119,11 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
1056
1119
  LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
1057
1120
  return -1;
1058
1121
  }
1122
+ if (chdir("/") == -1)
1123
+ {
1124
+ LSAPI_perror_r(pReq, "LSAPI: chdir() after chroot", NULL);
1125
+ return -1;
1126
+ }
1059
1127
  }
1060
1128
  rv = setuid(uid);
1061
1129
  if (rv == -1)
@@ -1070,12 +1138,13 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p
1070
1138
  return 0;
1071
1139
  }
1072
1140
 
1073
- static int lsapi_suexec_auth( LSAPI_Request *pReq,
1074
- char * pAuth, int len, char * pUgid, int ugidLen )
1141
+ static int lsapi_suexec_auth(char *pAuth, int len, char *pUgid, int ugidLen)
1075
1142
  {
1076
1143
  lsapi_MD5_CTX md5ctx;
1077
1144
  unsigned char achMD5[16];
1078
- if ( len < 32 )
1145
+ unsigned char diff = 0;
1146
+ int i;
1147
+ if (len != 32 || ugidLen != 8)
1079
1148
  return -1;
1080
1149
  memmove( achMD5, pAuth + 16, 16 );
1081
1150
  memmove( pAuth + 16, s_secret, 16 );
@@ -1083,21 +1152,89 @@ static int lsapi_suexec_auth( LSAPI_Request *pReq,
1083
1152
  lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
1084
1153
  lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
1085
1154
  lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
1086
- if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
1155
+ for (i = 0; i < 16; ++i)
1156
+ diff |= achMD5[i] ^ (unsigned char)pAuth[i + 16];
1157
+ if (diff == 0)
1087
1158
  return 0;
1088
1159
  return 1;
1089
1160
  }
1090
1161
 
1091
1162
 
1163
+ static int lsapi_special_env_is(const struct LSAPI_key_value_pair *pEnv,
1164
+ const char *name)
1165
+ {
1166
+ size_t len;
1167
+ if (!pEnv || !pEnv->pKey || !name || pEnv->keyLen < 1)
1168
+ return 0;
1169
+ len = strlen(name);
1170
+ return pEnv->keyLen == (int)len + 1
1171
+ && pEnv->pKey[0] == '\0'
1172
+ && memcmp(pEnv->pKey + 1, name, len) == 0;
1173
+ }
1174
+
1175
+
1176
+ static void lsapi_process_suexec_auth(LSAPI_Request *pReq,
1177
+ uid_t *uid, gid_t *gid)
1178
+ {
1179
+ struct LSAPI_key_value_pair *pAuth;
1180
+ struct LSAPI_key_value_pair *pUgid;
1181
+ uint32_t ugid[2];
1182
+ int count;
1183
+
1184
+ if (!pReq || !pReq->m_pHeader || !uid || !gid)
1185
+ return;
1186
+ count = pReq->m_pHeader->m_cntSpecialEnv;
1187
+ if (count < 1 || !pReq->m_pSpecialEnvList)
1188
+ return;
1189
+
1190
+ pAuth = pReq->m_pSpecialEnvList + count - 1;
1191
+ if (!lsapi_special_env_is(pAuth, "SUEXEC_AUTH"))
1192
+ return;
1193
+
1194
+ /* Never expose the authentication record to the application, including
1195
+ * malformed requests where the matching SUEXEC_UGID record is absent. */
1196
+ --pReq->m_pHeader->m_cntSpecialEnv;
1197
+ if (count < 2)
1198
+ {
1199
+ lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n");
1200
+ *uid = 0;
1201
+ goto clear_auth;
1202
+ }
1203
+
1204
+ pUgid = pAuth - 1;
1205
+ if (!lsapi_special_env_is(pUgid, "SUEXEC_UGID"))
1206
+ {
1207
+ lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n");
1208
+ *uid = 0;
1209
+ goto clear_auth;
1210
+ }
1211
+
1212
+ --pReq->m_pHeader->m_cntSpecialEnv;
1213
+ if (lsapi_suexec_auth(pAuth->pValue, pAuth->valLen,
1214
+ pUgid->pValue, pUgid->valLen) == 0)
1215
+ {
1216
+ memcpy(ugid, pUgid->pValue, sizeof(ugid));
1217
+ *uid = ugid[0];
1218
+ *gid = ugid[1];
1219
+ }
1220
+ else
1221
+ {
1222
+ lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n");
1223
+ *uid = 0;
1224
+ }
1225
+
1226
+ clear_auth:
1227
+ if (pAuth->pValue && pAuth->valLen > 0)
1228
+ memset(pAuth->pValue, 0, (size_t)pAuth->valLen);
1229
+ }
1230
+
1231
+
1092
1232
  static int lsapi_changeUGid( LSAPI_Request * pReq )
1093
1233
  {
1094
- int uid = s_defaultUid;
1095
- int gid = s_defaultGid;
1234
+ uid_t uid = s_defaultUid;
1235
+ gid_t gid = s_defaultGid;
1096
1236
  const char *pStderrLog;
1097
1237
  const char *pChroot = NULL;
1098
- struct LSAPI_key_value_pair * pEnv;
1099
- struct LSAPI_key_value_pair * pAuth;
1100
- int i;
1101
1238
  if ( s_uid )
1102
1239
  return 0;
1103
1240
  //with special ID 0x00
@@ -1105,48 +1242,10 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
1105
1242
  //first one should be MD5( nonce + lscgid secret )
1106
1243
  //remember to clear the secret after verification
1107
1244
  //it should be set at the end of special env
1108
- i = pReq->m_pHeader->m_cntSpecialEnv - 1;
1109
- if ( i >= 0 )
1110
- {
1111
- pEnv = pReq->m_pSpecialEnvList + i;
1112
- if (( *pEnv->pKey == '\000' )&&
1113
- ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
1114
- {
1115
- --pReq->m_pHeader->m_cntSpecialEnv;
1116
- pAuth = pEnv--;
1117
- if (( *pEnv->pKey == '\000' )&&
1118
- ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
1119
- {
1120
- --pReq->m_pHeader->m_cntSpecialEnv;
1121
- uid = *(uint32_t *)pEnv->pValue;
1122
- gid = *(((uint32_t *)pEnv->pValue) + 1 );
1123
- //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
1124
- }
1125
- else
1126
- {
1127
- lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" );
1128
- pEnv = NULL;
1129
- }
1130
- if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
1131
- {
1132
- //read UID, GID from specialEnv
1133
-
1134
- }
1135
- else
1136
- {
1137
- //authentication error
1138
- lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
1139
- uid = 0;
1140
- }
1141
- }
1142
- else
1143
- {
1144
- //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" );
1145
- }
1146
- }
1245
+ lsapi_process_suexec_auth(pReq, &uid, &gid);
1147
1246
 
1148
1247
 
1149
- if ( !uid )
1248
+ if (!uid || !gid)
1150
1249
  {
1151
1250
  uid = s_defaultUid;
1152
1251
  gid = s_defaultGid;
@@ -1178,8 +1277,22 @@ static int lsapi_changeUGid( LSAPI_Request * pReq )
1178
1277
  static int parseContentLenFromHeader(LSAPI_Request * pReq)
1179
1278
  {
1180
1279
  const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
1181
- if ( pContentLen )
1182
- pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
1280
+ char *pEnd;
1281
+ long long len;
1282
+ /* A missing Content-Length is valid for chunked HTTP/1 requests and for
1283
+ * HTTP/2 or HTTP/3 streams. Keep the protocol's unknown-length sentinel
1284
+ * in that case; producers that buffer the body may replace it with the
1285
+ * decoded length before forwarding the request. */
1286
+ if (!pContentLen)
1287
+ return 0;
1288
+
1289
+ errno = 0;
1290
+ len = strtoll(pContentLen, &pEnd, 10);
1291
+ while (*pEnd && isspace((unsigned char)*pEnd))
1292
+ ++pEnd;
1293
+ if (errno == ERANGE || pEnd == pContentLen || *pEnd || len < 0)
1294
+ return -1;
1295
+ pReq->m_reqBodyLen = len;
1183
1296
  return 0;
1184
1297
  }
1185
1298
 
@@ -1187,14 +1300,31 @@ static int parseContentLenFromHeader(LSAPI_Request * pReq)
1187
1300
  static int parseRequest( LSAPI_Request * pReq, int totalLen )
1188
1301
  {
1189
1302
  int shouldFixEndian;
1190
- char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
1191
- char * pEnd = pReq->m_pReqBuf + totalLen;
1303
+ char *pBegin;
1304
+ char *pEnd;
1305
+ size_t used;
1306
+ size_t aligned;
1307
+ size_t remaining;
1308
+ size_t unknownSize;
1309
+
1310
+ if (!pReq || !pReq->m_pReqBuf || totalLen < (int)sizeof(struct lsapi_req_header)
1311
+ || totalLen > pReq->m_reqBufSize)
1312
+ return -1;
1313
+ pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
1314
+ pEnd = pReq->m_pReqBuf + totalLen;
1192
1315
  shouldFixEndian = ( LSAPI_ENDIAN != (
1193
1316
  pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
1194
1317
  if ( shouldFixEndian )
1195
1318
  {
1196
1319
  fixEndian( pReq );
1197
1320
  }
1321
+ if (pReq->m_pHeader->m_cntSpecialEnv < 0
1322
+ || pReq->m_pHeader->m_cntSpecialEnv > 8192
1323
+ || pReq->m_pHeader->m_cntEnv < 0
1324
+ || pReq->m_pHeader->m_cntEnv > 8192
1325
+ || pReq->m_pHeader->m_cntUnknownHeaders < 0
1326
+ || pReq->m_pHeader->m_httpHeaderLen < 0)
1327
+ return -1;
1198
1328
  if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
1199
1329
  allocateEnvList( &pReq->m_pSpecialEnvList,
1200
1330
  &pReq->m_specialEnvListSize,
@@ -1228,21 +1358,46 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
1228
1358
  pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1229
1359
  pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1230
1360
  pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1361
+ if (!memchr(pReq->m_pScriptFile, '\0',
1362
+ (size_t)(pEnd - pReq->m_pScriptFile))
1363
+ || !memchr(pReq->m_pScriptName, '\0',
1364
+ (size_t)(pEnd - pReq->m_pScriptName))
1365
+ || !memchr(pReq->m_pQueryString, '\0',
1366
+ (size_t)(pEnd - pReq->m_pQueryString))
1367
+ || !memchr(pReq->m_pRequestMethod, '\0',
1368
+ (size_t)(pEnd - pReq->m_pRequestMethod)))
1369
+ return -1;
1231
1370
 
1232
- pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1371
+ used = (size_t)(pBegin - pReq->m_pReqBuf);
1372
+ if (used > (size_t)totalLen || used > SIZE_MAX - 7)
1373
+ return -1;
1374
+ aligned = (used + 7) & ~(size_t)7;
1375
+ if (aligned > (size_t)totalLen)
1376
+ return -1;
1377
+ pBegin = pReq->m_pReqBuf + aligned;
1378
+ remaining = (size_t)(pEnd - pBegin);
1379
+ if (remaining < sizeof(struct lsapi_http_header_index))
1380
+ return -1;
1233
1381
  pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1234
1382
  pBegin += sizeof( struct lsapi_http_header_index );
1235
1383
 
1236
1384
  pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1237
- pBegin += sizeof( struct lsapi_header_offset) *
1238
- pReq->m_pHeader->m_cntUnknownHeaders;
1385
+ remaining = (size_t)(pEnd - pBegin);
1386
+ if ((size_t)pReq->m_pHeader->m_cntUnknownHeaders
1387
+ > remaining / sizeof(struct lsapi_header_offset))
1388
+ return -1;
1389
+ unknownSize = sizeof(struct lsapi_header_offset)
1390
+ * (size_t)pReq->m_pHeader->m_cntUnknownHeaders;
1391
+ pBegin += unknownSize;
1239
1392
 
1240
1393
  pReq->m_pHttpHeader = pBegin;
1241
- pBegin += pReq->m_pHeader->m_httpHeaderLen;
1242
- if ( pBegin != pEnd )
1394
+ remaining = (size_t)(pEnd - pBegin);
1395
+ if ((size_t)pReq->m_pHeader->m_httpHeaderLen != remaining)
1243
1396
  {
1244
- lsapi_log("Request header does match total size, total: %d, "
1245
- "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
1397
+ lsapi_log("Request header does not match total size, total: %d, "
1398
+ "real: %ld\n", totalLen,
1399
+ pBegin - pReq->m_pReqBuf
1400
+ + pReq->m_pHeader->m_httpHeaderLen );
1246
1401
  return -1;
1247
1402
  }
1248
1403
  if ( shouldFixEndian )
@@ -1259,7 +1414,8 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen )
1259
1414
  pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1260
1415
  if ( pReq->m_reqBodyLen == -2 )
1261
1416
  {
1262
- parseContentLenFromHeader(pReq);
1417
+ if (parseContentLenFromHeader(pReq) == -1)
1418
+ return -1;
1263
1419
  }
1264
1420
 
1265
1421
  return 0;
@@ -1356,7 +1512,8 @@ static int readReq( LSAPI_Request * pReq )
1356
1512
 
1357
1513
  while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1358
1514
  {
1359
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1515
+ len = lsapi_read(pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead,
1516
+ pReq->m_reqBufSize - pReq->m_bufRead);
1360
1517
  if ( len <= 0 )
1361
1518
  return -1;
1362
1519
  pReq->m_bufRead += len;
@@ -1369,6 +1526,11 @@ static int readReq( LSAPI_Request * pReq )
1369
1526
  lsapi_log("packetLen < 0\n");
1370
1527
  return -1;
1371
1528
  }
1529
+ if (packetLen < (int)sizeof(struct lsapi_req_header))
1530
+ {
1531
+ lsapi_log("packetLen < request header size\n");
1532
+ return -1;
1533
+ }
1372
1534
  if ( packetLen > LSAPI_MAX_HEADER_LEN )
1373
1535
  {
1374
1536
  lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
@@ -1460,6 +1622,16 @@ void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
1460
1622
  }
1461
1623
 
1462
1624
 
1625
+ void LSAPI_Set_Fork_Hooks(LSAPI_Fork_Hook_pf before,
1626
+ LSAPI_Fork_Hook_pf after_parent,
1627
+ LSAPI_Fork_Hook_pf after_child)
1628
+ {
1629
+ s_fork_before = before;
1630
+ s_fork_after_parent = after_parent;
1631
+ s_fork_after_child = after_child;
1632
+ }
1633
+
1634
+
1463
1635
  int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1464
1636
  {
1465
1637
  int newfd;
@@ -1467,21 +1639,44 @@ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1467
1639
  return -1;
1468
1640
  memset( pReq, 0, sizeof( LSAPI_Request ) );
1469
1641
  if ( allocateIovec( pReq, 16 ) == -1 )
1642
+ {
1643
+ LSAPI_Release_r(pReq);
1470
1644
  return -1;
1645
+ }
1471
1646
  pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1472
1647
  if ( !pReq->m_pRespBuf )
1648
+ {
1649
+ LSAPI_Release_r(pReq);
1473
1650
  return -1;
1651
+ }
1474
1652
  pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1475
1653
  pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1476
1654
  pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1477
1655
  if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1656
+ {
1657
+ LSAPI_Release_r(pReq);
1478
1658
  return -1;
1659
+ }
1479
1660
 
1480
1661
  if ( fd == STDIN_FILENO )
1481
1662
  {
1482
1663
  fd = dup( fd );
1664
+ if (fd == -1)
1665
+ {
1666
+ LSAPI_Release_r(pReq);
1667
+ return -1;
1668
+ }
1483
1669
  newfd = open( "/dev/null", O_RDWR );
1484
- dup2( newfd, STDIN_FILENO );
1670
+ if (newfd == -1 || dup2(newfd, STDIN_FILENO) == -1)
1671
+ {
1672
+ if (newfd != -1)
1673
+ close(newfd);
1674
+ close(fd);
1675
+ LSAPI_Release_r(pReq);
1676
+ return -1;
1677
+ }
1678
+ if (newfd != STDIN_FILENO)
1679
+ close(newfd);
1485
1680
  }
1486
1681
 
1487
1682
  if ( isPipe( fd ) )
@@ -1656,6 +1851,8 @@ void LSAPI_Reset_r( LSAPI_Request * pReq )
1656
1851
 
1657
1852
  int LSAPI_Release_r( LSAPI_Request * pReq )
1658
1853
  {
1854
+ if (!pReq)
1855
+ return -1;
1659
1856
  if ( pReq->m_pReqBuf )
1660
1857
  free( pReq->m_pReqBuf );
1661
1858
  if ( pReq->m_pSpecialEnvList )
@@ -1664,6 +1861,13 @@ int LSAPI_Release_r( LSAPI_Request * pReq )
1664
1861
  free( pReq->m_pEnvList );
1665
1862
  if ( pReq->m_pRespHeaderBuf )
1666
1863
  free( pReq->m_pRespHeaderBuf );
1864
+ if ( pReq->m_pRespBuf )
1865
+ free( pReq->m_pRespBuf );
1866
+ if ( pReq->m_pIovec )
1867
+ free( pReq->m_pIovec );
1868
+ memset(pReq, 0, sizeof(*pReq));
1869
+ pReq->m_fdListen = -1;
1870
+ pReq->m_fd = -1;
1667
1871
  return 0;
1668
1872
  }
1669
1873
 
@@ -1690,11 +1894,13 @@ static int readBodyToReqBuf( LSAPI_Request * pReq )
1690
1894
  {
1691
1895
  off_t bodyLeft;
1692
1896
  ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1897
+ bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1898
+ if (bodyLeft <= 0)
1899
+ return 0;
1693
1900
  if ( len > 0 )
1694
- return len;
1901
+ return len > bodyLeft ? bodyLeft : len;
1695
1902
  pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1696
1903
 
1697
- bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1698
1904
  len = pReq->m_reqBufSize - pReq->m_bufRead;
1699
1905
  if ( len < 0 )
1700
1906
  return -1;
@@ -1712,6 +1918,8 @@ int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1712
1918
  {
1713
1919
  if (!pReq || (pReq->m_fd ==-1) )
1714
1920
  return EOF;
1921
+ if (pReq->m_reqBodyRead >= pReq->m_reqBodyLen)
1922
+ return EOF;
1715
1923
  if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1716
1924
  {
1717
1925
  if ( readBodyToReqBuf( pReq ) <= 0 )
@@ -1730,20 +1938,18 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in
1730
1938
  char * pBufCur = pBuf;
1731
1939
  char * pCur;
1732
1940
  char * p;
1733
- if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF)
1941
+ if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF || bufLen == 0
1942
+ || bufLen > (size_t)SSIZE_MAX)
1734
1943
  return -1;
1735
1944
  *getLF = 0;
1736
1945
  while( (left = pBufEnd - pBufCur ) > 0 )
1737
1946
  {
1738
1947
 
1739
- len = pReq->m_bufRead - pReq->m_bufProcessed;
1740
- if ( len <= 0 )
1948
+ len = readBodyToReqBuf(pReq);
1949
+ if (len <= 0)
1741
1950
  {
1742
- if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1743
- {
1744
- *getLF = 1;
1745
- break;
1746
- }
1951
+ *getLF = 1;
1952
+ break;
1747
1953
  }
1748
1954
  if ( len > left )
1749
1955
  len = left;
@@ -1774,7 +1980,7 @@ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1774
1980
  ssize_t len;
1775
1981
  off_t total;
1776
1982
  /* char *pOldBuf = pBuf; */
1777
- if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
1983
+ if (!pReq || pReq->m_fd == -1 || !pBuf || bufLen > (size_t)SSIZE_MAX)
1778
1984
  return -1;
1779
1985
 
1780
1986
  total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
@@ -1828,7 +2034,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1828
2034
  ssize_t packetLen;
1829
2035
  int skip = 0;
1830
2036
 
1831
- if (!pReq || !pBuf)
2037
+ if (!pReq || !pBuf || len > (size_t)SSIZE_MAX)
1832
2038
  return -1;
1833
2039
  if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1834
2040
  return len;
@@ -1954,7 +2160,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1954
2160
 
1955
2161
  end:
1956
2162
  *off += written;
1957
- return 0;
2163
+ return written;
1958
2164
  }
1959
2165
  #endif
1960
2166
 
@@ -1965,7 +2171,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1965
2171
  ssize_t ret;
1966
2172
  off_t len = size;
1967
2173
  ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1968
- if (( ret == 0 )&&( len > 0 ))
2174
+ if (len > 0)
1969
2175
  {
1970
2176
  ret = len;
1971
2177
  *off += len;
@@ -2013,28 +2219,120 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
2013
2219
  }
2014
2220
  #endif
2015
2221
 
2222
+ #ifndef LSAPI_GSENDFILE
2223
+ #define LSAPI_GSENDFILE gsendfile
2224
+ #endif
2225
+
2226
+
2227
+ static int lsapi_sendfile_write_header(LSAPI_Request *pReq,
2228
+ const struct lsapi_packet_header *header)
2229
+ {
2230
+ const char *p = (const char *)header;
2231
+ size_t left = LSAPI_PACKET_HEADER_LEN;
2232
+
2233
+ while (left > 0 && g_running)
2234
+ {
2235
+ ssize_t written = write(pReq->m_fd, p, left);
2236
+ if (written > 0)
2237
+ {
2238
+ p += written;
2239
+ left -= (size_t)written;
2240
+ }
2241
+ else if (written == -1 && errno == EINTR)
2242
+ continue;
2243
+ else
2244
+ break;
2245
+ }
2246
+ if (left == 0)
2247
+ return 0;
2248
+ lsapi_close_connection(pReq);
2249
+ return -1;
2250
+ }
2251
+
2016
2252
 
2017
2253
  ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
2018
2254
  {
2019
- struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2020
- if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
2255
+ struct lsapi_packet_header *pHeader;
2256
+ struct stat st;
2257
+ size_t remaining;
2258
+ size_t totalSent = 0;
2259
+
2260
+ if (!pReq || pReq->m_fd == -1 || fdIn == -1 || !off || *off < 0
2261
+ || size > (size_t)SSIZE_MAX)
2021
2262
  return -1;
2263
+ if (fstat(fdIn, &st) == 0 && S_ISREG(st.st_mode))
2264
+ {
2265
+ uintmax_t available;
2266
+ if (*off >= st.st_size)
2267
+ return 0;
2268
+ available = (uintmax_t)(st.st_size - *off);
2269
+ if ((uintmax_t)size > available)
2270
+ size = (size_t)available;
2271
+ }
2272
+ if (size == 0)
2273
+ return 0;
2274
+
2275
+ pHeader = pReq->m_respPktHeader;
2022
2276
  if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2023
2277
  {
2024
- LSAPI_FinalizeRespHeaders_r( pReq );
2278
+ if (LSAPI_FinalizeRespHeaders_r(pReq) == -1)
2279
+ return -1;
2025
2280
  }
2026
2281
  pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2027
2282
 
2028
- LSAPI_Flush_r(pReq);
2029
-
2030
- lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2031
- size + LSAPI_PACKET_HEADER_LEN );
2032
-
2033
-
2034
- if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
2283
+ if (LSAPI_Flush_r(pReq) == -1)
2035
2284
  return -1;
2036
2285
 
2037
- return gsendfile( pReq->m_fd, fdIn, off, size );
2286
+ remaining = size;
2287
+ while (remaining > 0)
2288
+ {
2289
+ size_t packetLeft = remaining;
2290
+ if (!g_running)
2291
+ {
2292
+ lsapi_close_connection(pReq);
2293
+ return -1;
2294
+ }
2295
+ if (packetLeft > LSAPI_MAX_DATA_PACKET_LEN)
2296
+ packetLeft = LSAPI_MAX_DATA_PACKET_LEN;
2297
+ lsapi_buildPacketHeader(pHeader, LSAPI_RESP_STREAM,
2298
+ (int)packetLeft + LSAPI_PACKET_HEADER_LEN);
2299
+ if (lsapi_sendfile_write_header(pReq, pHeader) == -1)
2300
+ return -1;
2301
+
2302
+ while (packetLeft > 0)
2303
+ {
2304
+ ssize_t sent;
2305
+ if (!g_running)
2306
+ {
2307
+ lsapi_close_connection(pReq);
2308
+ return -1;
2309
+ }
2310
+ sent = LSAPI_GSENDFILE(pReq->m_fd, fdIn, off, packetLeft);
2311
+ if (sent > 0 && (size_t)sent <= packetLeft)
2312
+ {
2313
+ packetLeft -= (size_t)sent;
2314
+ remaining -= (size_t)sent;
2315
+ totalSent += (size_t)sent;
2316
+ }
2317
+ else if (sent == -1 && errno == EINTR)
2318
+ {
2319
+ if (!g_running)
2320
+ {
2321
+ lsapi_close_connection(pReq);
2322
+ return -1;
2323
+ }
2324
+ continue;
2325
+ }
2326
+ else
2327
+ {
2328
+ /* Once a packet header has been written, the connection must
2329
+ * not be reused unless its complete payload is delivered. */
2330
+ lsapi_close_connection(pReq);
2331
+ return -1;
2332
+ }
2333
+ }
2334
+ }
2335
+ return (ssize_t)totalSent;
2038
2336
  }
2039
2337
 
2040
2338
 
@@ -2116,7 +2414,7 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le
2116
2414
  struct iovec iov[2];
2117
2415
  struct iovec *pIov;
2118
2416
 
2119
- if ( !pReq )
2417
+ if (!pReq || !pBuf || len > (size_t)SSIZE_MAX)
2120
2418
  return -1;
2121
2419
  if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen)
2122
2420
  return write( 2, pBuf, len );
@@ -2196,7 +2494,7 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
2196
2494
 
2197
2495
  while(( pKey < pKeyEnd )&&( *p ))
2198
2496
  {
2199
- char ch = toupper( *pKey );
2497
+ char ch = toupper((unsigned char)*pKey);
2200
2498
  if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
2201
2499
  break;
2202
2500
  ++p; ++pKey;
@@ -2220,10 +2518,19 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
2220
2518
 
2221
2519
  char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
2222
2520
  {
2223
- struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
2224
- struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
2521
+ struct LSAPI_key_value_pair *pBegin;
2522
+ struct LSAPI_key_value_pair *pEnd;
2225
2523
  if ( !pReq || !name )
2226
2524
  return NULL;
2525
+ if (!pReq->m_pHeader || pReq->m_pHeader->m_cntEnv <= 0
2526
+ || !pReq->m_pEnvList)
2527
+ {
2528
+ if (strncmp(name, "HTTP_", 5) == 0 && pReq->m_pHeaderIndex)
2529
+ return GetHeaderVar(pReq, name);
2530
+ return NULL;
2531
+ }
2532
+ pBegin = pReq->m_pEnvList;
2533
+ pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
2227
2534
  if ( strncmp( name, "HTTP_", 5 ) == 0 )
2228
2535
  {
2229
2536
  return GetHeaderVar( pReq, name );
@@ -2249,8 +2556,9 @@ struct _headerInfo
2249
2556
 
2250
2557
  int compareValueLocation(const void * v1, const void *v2 )
2251
2558
  {
2252
- return ((const struct _headerInfo *)v1)->_value -
2253
- ((const struct _headerInfo *)v2)->_value;
2559
+ const char *p1 = ((const struct _headerInfo *)v1)->_value;
2560
+ const char *p2 = ((const struct _headerInfo *)v2)->_value;
2561
+ return (p1 > p2) - (p1 < p2);
2254
2562
  }
2255
2563
 
2256
2564
 
@@ -2380,7 +2688,7 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2380
2688
  if ( ch == '-' )
2381
2689
  *p++ = '_';
2382
2690
  else
2383
- *p++ = toupper( ch );
2691
+ *p++ = toupper((unsigned char)ch);
2384
2692
  }
2385
2693
  *p = 0;
2386
2694
  keyLen += 5;
@@ -2477,7 +2785,8 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2477
2785
  int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2478
2786
  const char * pHeaderValue )
2479
2787
  {
2480
- int nameLen, valLen, len;
2788
+ size_t nameLen, valLen;
2789
+ int len;
2481
2790
  if ( !pReq || !pHeaderName || !pHeaderValue )
2482
2791
  return -1;
2483
2792
  if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
@@ -2486,7 +2795,8 @@ int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2486
2795
  return -1;
2487
2796
  nameLen = strlen( pHeaderName );
2488
2797
  valLen = strlen( pHeaderValue );
2489
- if ( nameLen == 0 )
2798
+ if (nameLen == 0 || nameLen > LSAPI_RESP_HTTP_HEADER_MAX
2799
+ || valLen > LSAPI_RESP_HTTP_HEADER_MAX)
2490
2800
  return -1;
2491
2801
  while( nameLen > 0 )
2492
2802
  {
@@ -2506,9 +2816,14 @@ int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2506
2816
  else
2507
2817
  break;
2508
2818
  }
2509
- len = nameLen + valLen + 1;
2510
- if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2819
+ if (memchr(pHeaderName, '\r', nameLen) || memchr(pHeaderName, '\n', nameLen)
2820
+ || memchr(pHeaderName, ':', nameLen)
2821
+ || memchr(pHeaderValue, '\r', valLen)
2822
+ || memchr(pHeaderValue, '\n', valLen))
2823
+ return -1;
2824
+ if (nameLen + valLen + 2 > SHRT_MAX)
2511
2825
  return -1;
2826
+ len = (int)(nameLen + valLen + 1);
2512
2827
 
2513
2828
  if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2514
2829
  {
@@ -2548,6 +2863,9 @@ int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2548
2863
  }
2549
2864
  if ( len <= 0 )
2550
2865
  return 0;
2866
+ if (len >= SHRT_MAX || memchr(pBuf, '\0', len)
2867
+ || memchr(pBuf, '\r', len) || memchr(pBuf, '\n', len))
2868
+ return -1;
2551
2869
  if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2552
2870
  {
2553
2871
  int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
@@ -2571,19 +2889,42 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2571
2889
  int fd;
2572
2890
  int flag = 1;
2573
2891
  int addr_len;
2892
+ struct stat st;
2893
+
2894
+ if (!pServerAddr)
2895
+ return -1;
2574
2896
 
2575
2897
  switch( pServerAddr->sa_family )
2576
2898
  {
2577
2899
  case AF_INET:
2578
- addr_len = 16;
2900
+ addr_len = sizeof(struct sockaddr_in);
2579
2901
  break;
2580
2902
  case AF_INET6:
2581
2903
  addr_len = sizeof( struct sockaddr_in6 );
2582
2904
  break;
2583
2905
  case AF_UNIX:
2584
- addr_len = sizeof( struct sockaddr_un );
2585
- unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2906
+ {
2907
+ const char *path = ((const struct sockaddr_un *)pServerAddr)->sun_path;
2908
+ size_t pathLen = strnlen(path,
2909
+ sizeof(((const struct sockaddr_un *)pServerAddr)->sun_path));
2910
+ if (pathLen == 0
2911
+ || pathLen == sizeof(((const struct sockaddr_un *)pServerAddr)->sun_path))
2912
+ return -1;
2913
+ addr_len = offsetof(struct sockaddr_un, sun_path) + pathLen + 1;
2914
+ if (lstat(path, &st) == 0)
2915
+ {
2916
+ if (!S_ISSOCK(st.st_mode))
2917
+ {
2918
+ errno = EEXIST;
2919
+ return -1;
2920
+ }
2921
+ if (unlink(path) == -1)
2922
+ return -1;
2923
+ }
2924
+ else if (errno != ENOENT)
2925
+ return -1;
2586
2926
  break;
2927
+ }
2587
2928
  default:
2588
2929
  return -1;
2589
2930
  }
@@ -2622,22 +2963,27 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2622
2963
  int doAddrInfo = 0;
2623
2964
  int port;
2624
2965
 
2625
- if ( !pBind )
2966
+ if ( !pBind || !pAddr )
2626
2967
  return -1;
2627
2968
 
2628
2969
  while( isspace( *pBind ) )
2629
2970
  ++pBind;
2630
2971
 
2631
- strncpy(achAddr, pBind, 255);
2632
- achAddr[255] = 0;
2972
+ if (strlen(pBind) >= sizeof(achAddr))
2973
+ return -1;
2974
+ strcpy(achAddr, pBind);
2633
2975
 
2634
2976
  switch( *p )
2635
2977
  {
2636
2978
  case '/':
2979
+ {
2980
+ size_t pathLen = strlen(p);
2981
+ if (pathLen >= sizeof(((struct sockaddr_un *)pAddr)->sun_path))
2982
+ return -1;
2637
2983
  pAddr->sa_family = AF_UNIX;
2638
- memccpy(((struct sockaddr_un *)pAddr)->sun_path, p, 0,
2639
- sizeof(((struct sockaddr_un *)pAddr)->sun_path));
2984
+ memcpy(((struct sockaddr_un *)pAddr)->sun_path, p, pathLen + 1);
2640
2985
  return 0;
2986
+ }
2641
2987
 
2642
2988
  case '[':
2643
2989
  pAddr->sa_family = AF_INET6;
@@ -2995,12 +3341,14 @@ static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
2995
3341
  s_pid_dump_debug_info = fork();
2996
3342
  if (s_pid_dump_debug_info == 0)
2997
3343
  {
2998
- snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
2999
- "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
3344
+ snprintf(achCmd, sizeof(achCmd),
3345
+ "PATH=/usr/bin:/bin:/usr/sbin:/sbin; export PATH; "
3346
+ "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
3347
+ "-ex \"bt\" >&2; lsof -p %d >&2",
3000
3348
  pStatus->m_pid, pStatus->m_pid );
3001
3349
  if ( system( achCmd ) == -1 )
3002
3350
  perror( "system()" );
3003
- exit( 0 );
3351
+ _exit( 0 );
3004
3352
  }
3005
3353
  }
3006
3354
 
@@ -3253,6 +3601,8 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3253
3601
  perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
3254
3602
  }
3255
3603
 
3604
+ if (s_fork_before)
3605
+ (*s_fork_before)();
3256
3606
  pid = fork();
3257
3607
 
3258
3608
  if ( !pid )
@@ -3260,6 +3610,8 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3260
3610
  setsid();
3261
3611
  if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3262
3612
  perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
3613
+ if (s_fork_after_child)
3614
+ (*s_fork_after_child)();
3263
3615
  g_prefork_server = NULL;
3264
3616
  s_ppid = getppid();
3265
3617
  s_pid = getpid();
@@ -3300,12 +3652,17 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3300
3652
  }
3301
3653
  else if ( pid == -1 )
3302
3654
  {
3303
- lsapi_perror("fork() failed, please increase process limit", errno);
3655
+ int fork_errno = errno;
3656
+ if (s_fork_after_parent)
3657
+ (*s_fork_after_parent)();
3658
+ lsapi_perror("fork() failed, please increase process limit", fork_errno);
3304
3659
  if (child_status)
3305
3660
  child_status->m_pid = 0;
3306
3661
  }
3307
3662
  else
3308
3663
  {
3664
+ if (s_fork_after_parent)
3665
+ (*s_fork_after_parent)();
3309
3666
  ++pServer->m_iCurChildren;
3310
3667
  if ( child_status )
3311
3668
  {
@@ -3397,6 +3754,24 @@ int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
3397
3754
  }
3398
3755
 
3399
3756
 
3757
+ /* Call in the parent instead of LSAPI_Postfork_Parent() when fork() failed
3758
+ * after LSAPI_Accept_Before_Fork(). */
3759
+ int LSAPI_Postfork_Failed(LSAPI_Request * pReq)
3760
+ {
3761
+ if (pReq->child_status)
3762
+ {
3763
+ pReq->child_status->m_pid = 0;
3764
+ pReq->child_status = NULL;
3765
+ }
3766
+ if (pReq->m_fd != -1)
3767
+ {
3768
+ close(pReq->m_fd);
3769
+ pReq->m_fd = -1;
3770
+ }
3771
+ return 0;
3772
+ }
3773
+
3774
+
3400
3775
  int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3401
3776
  {
3402
3777
  time_t lastTime = 0;
@@ -3405,6 +3780,8 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3405
3780
  struct timeval timeout;
3406
3781
  int wait_secs = 0;
3407
3782
  int ret = 0;
3783
+ int accepted = 0;
3784
+ sigset_t chld_mask, orig_mask;
3408
3785
 
3409
3786
  lsapi_prefork_server * pServer = g_prefork_server;
3410
3787
 
@@ -3420,6 +3797,13 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3420
3797
  perror( "Can't set signal handler for SIGCHILD" );
3421
3798
  return -1;
3422
3799
  }
3800
+ /* The caller forks between calls, with the caller's SIGCHLD handler in
3801
+ * place; reap workers that exited meanwhile, or they stay counted. */
3802
+ sigemptyset(&chld_mask);
3803
+ sigaddset(&chld_mask, SIGCHLD);
3804
+ sigprocmask(SIG_BLOCK, &chld_mask, &orig_mask);
3805
+ lsapi_sigchild(SIGCHLD);
3806
+ sigprocmask(SIG_SETMASK, &orig_mask, NULL);
3423
3807
 
3424
3808
  /* Set up handler to kill children upon exit */
3425
3809
  act.sa_flags = 0;
@@ -3436,7 +3820,9 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3436
3820
  s_stop = 0;
3437
3821
  pReq->m_reqState = 0;
3438
3822
 
3439
- while(!s_stop)
3823
+ /* A stop signal that arrives between calls (while the caller forks) is
3824
+ * handled by lsapi_siguser1(), which only clears g_running. */
3825
+ while(!s_stop && g_running)
3440
3826
  {
3441
3827
  if (s_proc_group_timer_cb != NULL) {
3442
3828
  s_proc_group_timer_cb(&s_ignore_pid);
@@ -3518,7 +3904,7 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3518
3904
  wait_secs = 0;
3519
3905
  pReq->child_status = find_child_status(0);
3520
3906
 
3521
- ret = 0;
3907
+ accepted = 1;
3522
3908
  break;
3523
3909
  }
3524
3910
  else
@@ -3537,7 +3923,7 @@ int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3537
3923
  sigaction(SIGINT, &old_int, 0);
3538
3924
  sigaction(SIGUSR1, &old_usr1, 0);
3539
3925
 
3540
- return ret;
3926
+ return accepted ? 0 : -1;
3541
3927
  }
3542
3928
 
3543
3929
 
@@ -3865,34 +4251,70 @@ static int lsapi_initSuEXEC(void)
3865
4251
  s_defaultGid = 10000;
3866
4252
  }
3867
4253
  }
4254
+ if (!s_defaultUid || !s_defaultGid)
4255
+ return -1;
3868
4256
  return 0;
3869
4257
  }
3870
4258
 
3871
4259
 
4260
+ static int lsapi_path_is_forbidden(const char *path)
4261
+ {
4262
+ return strcmp(path, "/etc") == 0 || strncmp(path, "/etc/", 5) == 0;
4263
+ }
4264
+
4265
+
3872
4266
  static int lsapi_check_path(const char *p, char *final, int max_len)
3873
4267
  {
3874
4268
  char resolved_path[PATH_MAX+1];
3875
- int len = 0;
3876
- char *end;
4269
+ char parent_path[PATH_MAX+1];
4270
+ size_t len = 0;
4271
+ size_t inputLen;
4272
+ char *slash;
4273
+
4274
+ if (!p || !*p || !final || max_len <= 1)
4275
+ {
4276
+ errno = EINVAL;
4277
+ return -1;
4278
+ }
4279
+ inputLen = strlen(p);
3877
4280
  if (*p != '/')
3878
4281
  {
3879
4282
  if (getcwd(final, max_len) == NULL)
3880
4283
  return -1;
3881
4284
  len = strlen(final);
3882
- *(final + len) = '/';
3883
- ++len;
4285
+ if (len + 1 >= (size_t)max_len)
4286
+ {
4287
+ errno = ENAMETOOLONG;
4288
+ return -1;
4289
+ }
4290
+ final[len++] = '/';
3884
4291
  }
3885
- end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3886
- if (!end)
4292
+ if (inputLen >= (size_t)max_len - len)
3887
4293
  {
3888
- errno = EINVAL;
4294
+ errno = ENAMETOOLONG;
3889
4295
  return -1;
3890
4296
  }
3891
- p = final;
3892
- if (realpath(p, resolved_path) == NULL
3893
- && errno != ENOENT && errno != EACCES)
3894
- return -1;
3895
- if (strncmp(resolved_path, "/etc/", 5) == 0)
4297
+ memcpy(final + len, p, inputLen + 1);
4298
+
4299
+ if (realpath(final, resolved_path) == NULL)
4300
+ {
4301
+ if (errno != ENOENT)
4302
+ return -1;
4303
+ memcpy(parent_path, final, strlen(final) + 1);
4304
+ slash = strrchr(parent_path, '/');
4305
+ if (!slash)
4306
+ {
4307
+ errno = EINVAL;
4308
+ return -1;
4309
+ }
4310
+ if (slash == parent_path)
4311
+ slash[1] = '\0';
4312
+ else
4313
+ *slash = '\0';
4314
+ if (realpath(parent_path, resolved_path) == NULL)
4315
+ return -1;
4316
+ }
4317
+ if (lsapi_path_is_forbidden(resolved_path))
3896
4318
  {
3897
4319
  errno = EPERM;
3898
4320
  return -1;
@@ -3903,7 +4325,14 @@ static int lsapi_check_path(const char *p, char *final, int max_len)
3903
4325
 
3904
4326
  static int lsapi_reopen_stderr2(const char *full_path)
3905
4327
  {
3906
- int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
4328
+ int flags = O_WRONLY | O_CREAT | O_APPEND;
4329
+ #ifdef O_CLOEXEC
4330
+ flags |= O_CLOEXEC;
4331
+ #endif
4332
+ #ifdef O_NOFOLLOW
4333
+ flags |= O_NOFOLLOW;
4334
+ #endif
4335
+ int newfd = open(full_path, flags, 0644);
3907
4336
  if (newfd == -1)
3908
4337
  {
3909
4338
  LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
@@ -3911,10 +4340,15 @@ static int lsapi_reopen_stderr2(const char *full_path)
3911
4340
  }
3912
4341
  if (newfd != 2)
3913
4342
  {
3914
- dup2(newfd, 2);
4343
+ if (dup2(newfd, 2) == -1)
4344
+ {
4345
+ close(newfd);
4346
+ return -1;
4347
+ }
3915
4348
  close(newfd);
3916
- dup2(2, 1);
3917
4349
  }
4350
+ if (dup2(2, 1) == -1)
4351
+ return -1;
3918
4352
  if (s_stderr_log_path && full_path != s_stderr_log_path)
3919
4353
  {
3920
4354
  free(s_stderr_log_path);
@@ -4074,7 +4508,14 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
4074
4508
  if ( lsapi_initSuEXEC() == -1 )
4075
4509
  return -1;
4076
4510
  #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
4077
- lsapi_initLVE();
4511
+ if (lsapi_initLVE() == -1)
4512
+ {
4513
+ /* Some historical callers ignored this function's return value.
4514
+ * Stop the accept loop as well so configured LVE enforcement can
4515
+ * never degrade silently. */
4516
+ g_running = 0;
4517
+ return -1;
4518
+ }
4078
4519
  #endif
4079
4520
  }
4080
4521
  unset_lsapi_envs();
@@ -4343,5 +4784,3 @@ int LSAPI_Inc_Req_Processed(int cnt)
4343
4784
  {
4344
4785
  return __atomic_add_fetch(s_global_counter, cnt, __ATOMIC_SEQ_CST);
4345
4786
  }
4346
-
4347
-