Skip to content

[Bug] Potential buffer overflow in php_cli_server_startup_workers #8989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
yiyuaner opened this issue Jul 13, 2022 · 4 comments
Closed

[Bug] Potential buffer overflow in php_cli_server_startup_workers #8989

yiyuaner opened this issue Jul 13, 2022 · 4 comments

Comments

@yiyuaner
Copy link
Contributor

Description

In the file sapi/cli/php_cli_server.c, the function php_cli_server_startup_workers has the following code:

void php_cli_server_startup_workers(void) {
    char *workers = getenv("PHP_CLI_SERVER_WORKERS");
    if (!workers) {
        return;
    }
    php_cli_server_workers_max = ZEND_ATOL(workers); 
    
    if (php_cli_server_workers_max > 1) { 
        php_cli_server_workers = calloc(
			php_cli_server_workers_max, sizeof(pid_t));
        ...
    }
}

The variable php_cli_server_workers_max is parsed from environment variable and thus is controlled. When setting php_cli_server_workers_max to a large value (e.g., INT64_MAX), the multiplication php_cli_server_workers_max * sizeof(pid_t) could wrap to a small value. A buffer smaller than expected will be allocated and this can lead to subsequent buffer overflow.

Notice that the C standard does not clearly states that calloc will check for multiplication overflow itself (see here). It will be better to also restrict the maximum value for php_cli_server_workers_max in the code.

PHP Version

github master

Operating System

No response

@devnexen
Copy link
Member

It will be better to also restrict the maximum value for php_cli_server_workers_max in the code.

strtoll here is, at least, a better fit in conjunction with ranges check (or using a wrapper "a la" strtonum).

@cmb69
Copy link
Member

cmb69 commented Jul 13, 2022

I agree that this should be improved, but setting a very large number is unlikely to work anyway, or is it?

@yiyuaner
Copy link
Contributor Author

I agree that this should be improved, but setting a very large number is unlikely to work anyway, or is it?

With a very large number for php_cli_server_workers_max, the actual buffer size of php_cli_server_workers is actually a small value due to the wrap-around. Then the following loop can lead to out of bound buffer access (only require fork to succeed for a small number of times):

for (php_cli_server_worker = 0;
       php_cli_server_worker < php_cli_server_workers_max;
       php_cli_server_worker++) {
    pid_t pid = fork();
    if (pid < 0) {
	/* no more forks allowed, work with what we have ... */
	php_cli_server_workers_max =
	php_cli_server_worker + 1;
	return;
    } else if (pid == 0) {
	return;
    } else {
	php_cli_server_workers[php_cli_server_worker] = pid;
    }
}

@devnexen
Copy link
Member

@yiyuaner Can you provide a PR ? if that's the case feel free ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants