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.
- checksums.yaml +4 -4
- data/README +11 -2
- data/examples/lsapi_with_cgi.rb +17 -2
- data/examples/testlsapi.rb +18 -1
- data/ext/lsapi/lsapilib.c +637 -198
- data/ext/lsapi/lsapilib.h +25 -4
- data/ext/lsapi/lsruby.c +388 -204
- data/lsapi.gemspec +2 -2
- data/rails/dispatch.lsapi +30 -2
- data/scripts/lsruby_runner.rb +33 -10
- metadata +3 -6
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 +
|
|
555
|
-
pReq->m_pIovecCur = p +
|
|
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 +
|
|
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 ((
|
|
621
|
-
(
|
|
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
|
-
|
|
632
|
-
|
|
633
|
-
|
|
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
|
-
|
|
636
|
-
while( pEnvList != pEnvEnd )
|
|
655
|
+
for (i = 0; i < count; ++i, ++pEnvList)
|
|
637
656
|
{
|
|
638
|
-
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
735
|
-
|
|
736
|
-
|
|
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
|
|
748
|
-
|| pCur->nameOff
|
|
749
|
-
|| pCur->
|
|
750
|
-
|| pCur->valueOff
|
|
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
|
-
|
|
786
|
-
|
|
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 (
|
|
826
|
+
if (setreuid(s_uid, uid) == 0)
|
|
789
827
|
{
|
|
790
|
-
int
|
|
791
|
-
if (
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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",
|
|
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
|
-
|
|
924
|
+
while (readLen < 16)
|
|
872
925
|
{
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1095
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
1182
|
-
|
|
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 *
|
|
1191
|
-
char *
|
|
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
|
-
|
|
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
|
-
|
|
1238
|
-
|
|
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
|
-
|
|
1242
|
-
if (
|
|
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,
|
|
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(
|
|
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(
|
|
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
|
|
1740
|
-
if (
|
|
1948
|
+
len = readBodyToReqBuf(pReq);
|
|
1949
|
+
if (len <= 0)
|
|
1741
1950
|
{
|
|
1742
|
-
|
|
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 ||
|
|
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
|
|
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 (
|
|
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 *
|
|
2020
|
-
|
|
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(
|
|
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
|
-
|
|
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 (
|
|
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 *
|
|
2224
|
-
struct LSAPI_key_value_pair *
|
|
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
|
-
|
|
2253
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
2510
|
-
|
|
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 =
|
|
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
|
-
|
|
2585
|
-
|
|
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
|
-
|
|
2632
|
-
|
|
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
|
-
|
|
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(
|
|
2999
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
3876
|
-
|
|
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
|
-
|
|
3883
|
-
|
|
4285
|
+
if (len + 1 >= (size_t)max_len)
|
|
4286
|
+
{
|
|
4287
|
+
errno = ENAMETOOLONG;
|
|
4288
|
+
return -1;
|
|
4289
|
+
}
|
|
4290
|
+
final[len++] = '/';
|
|
3884
4291
|
}
|
|
3885
|
-
|
|
3886
|
-
if (!end)
|
|
4292
|
+
if (inputLen >= (size_t)max_len - len)
|
|
3887
4293
|
{
|
|
3888
|
-
errno =
|
|
4294
|
+
errno = ENAMETOOLONG;
|
|
3889
4295
|
return -1;
|
|
3890
4296
|
}
|
|
3891
|
-
p
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
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
|
|
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
|
-
|