39
39
#include <sys/resource.h>
40
40
#endif
41
41
42
+ #if defined(HAVE_EXECVEAT )
43
+ #include <fcntl.h>
44
+ #include <unistd.h>
45
+ #endif
46
+
42
47
#ifdef HAVE_WAITID
43
48
#if defined (HAVE_DECL_P_ALL ) && HAVE_DECL_P_ALL == 1
44
49
#define HAVE_POSIX_IDTYPES 1
@@ -617,6 +622,54 @@ PHP_FUNCTION(pcntl_wstopsig)
617
622
}
618
623
/* }}} */
619
624
625
+ #ifdef HAVE_EXECVEAT
626
+ static zend_always_inline zend_result php_execve (const char * path , char * * argv , char * * envp ) {
627
+ int fd = open (path , O_RDONLY | O_CLOEXEC );
628
+ if (fd < 0 ) {
629
+ return FAILURE ;
630
+ }
631
+ #ifdef AT_EXECVE_CHECK
632
+ // Linux >= 6.14 allows to check if `path` is allowed
633
+ // for execution per kernel security policy (w/o actually running it)
634
+ if (execveat (fd , "" , argv , envp , AT_EMPTY_PATH | AT_EXECVE_CHECK ) < 0 ) {
635
+ close (fd );
636
+ return FAILURE ;
637
+ }
638
+ #endif
639
+ if (execveat (fd , "" , argv , envp , AT_EMPTY_PATH ) < 0 ) {
640
+ close (fd );
641
+ return FAILURE ;
642
+ }
643
+ return SUCCESS ;
644
+ }
645
+
646
+ static zend_always_inline zend_result php_execv (const char * path , char * * argv ) {
647
+ int fd = open (path , O_RDONLY | O_CLOEXEC );
648
+ if (fd < 0 ) {
649
+ return FAILURE ;
650
+ }
651
+ #ifdef AT_EXECVE_CHECK
652
+ if (execveat (fd , "" , argv , NULL , AT_EMPTY_PATH | AT_EXECVE_CHECK ) < 0 ) {
653
+ close (fd );
654
+ return FAILURE ;
655
+ }
656
+ #endif
657
+ if (execveat (fd , "" , argv , NULL , AT_EMPTY_PATH ) < 0 ) {
658
+ close (fd );
659
+ return FAILURE ;
660
+ }
661
+ return SUCCESS ;
662
+ }
663
+ #else
664
+ static zend_always_inline zend_result php_execve (const char * path , char * * argv , char * * envp ) {
665
+ return execve (path , argv , envp ) == 0 ? SUCCESS : FAILURE ;
666
+ }
667
+
668
+ static zend_always_inline zend_result php_execv (const char * path , char * * argv ) {
669
+ return execv (path , argv ) == 0 ? SUCCESS : FAILURE ;
670
+ }
671
+ #endif
672
+
620
673
/* {{{ Executes specified program in current process space as defined by exec(2) */
621
674
PHP_FUNCTION (pcntl_exec )
622
675
{
@@ -716,7 +769,7 @@ PHP_FUNCTION(pcntl_exec)
716
769
} ZEND_HASH_FOREACH_END ();
717
770
* (pair ) = NULL ;
718
771
719
- if (execve (path , argv , envp ) == -1 ) {
772
+ if (php_execve (path , argv , envp ) == FAILURE ) {
720
773
PCNTL_G (last_error ) = errno ;
721
774
php_error_docref (NULL , E_WARNING , "Error has occurred: (errno %d) %s" , errno , strerror (errno ));
722
775
}
@@ -727,7 +780,7 @@ PHP_FUNCTION(pcntl_exec)
727
780
efree (envp );
728
781
} else {
729
782
730
- if (execv (path , argv ) == -1 ) {
783
+ if (php_execv (path , argv ) == FAILURE ) {
731
784
PCNTL_G (last_error ) = errno ;
732
785
php_error_docref (NULL , E_WARNING , "Error has occurred: (errno %d) %s" , errno , strerror (errno ));
733
786
}
0 commit comments