Phpredis: Segmentation fault when using redis 5.3.0 for sessions

Created on 2 Jul 2020  路  3Comments  路  Source: phpredis/phpredis

Expected behaviour

Redis can be used for session handling

Actual behaviour

Segmentation fault on session_start()

I'm seeing this behaviour on

  • OS: Linux 4.19.76
  • Redis: 4.0-alpine3.9
  • PHP: 7.2.14
  • phpredis: 5.3.0

Steps to reproduce, backtrace or example script

Segfault happens during session_start:

<?php
session_start();

Is all the code necessary to reproduce it.

I haven't had a chance to rebuild php + phpredis with debugging info but here's a gdb backtrace:

(gdb) run < foo.php
Starting program: /usr/local/bin/php < foo.php
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
strlen () at ../sysdeps/x86_64/strlen.S:106
106     ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) bt
#0  strlen () at ../sysdeps/x86_64/strlen.S:106
#1  0x00007fb41cc1863e in redis_sock_create (host=host@entry=0x7fb41f8760f0 "tcp://redis", host_len=11, port=6379, timeout=1, read_timeout=0, persistent=1, persistent_id=0x18 <error: Cannot access memory at address 0x18>,
    retry_interval=<optimized out>) at /tmp/pear/temp/redis/library.c:2102
#2  0x00007fb41cc1f054 in ps_open_redis (mod_data=0x55c095a238b8 <ps_globals+88>, save_path=0x55c09765a8d8 "tcp://redis:6379?persistent=1&timeout=1.0", session_name=<optimized out>) at /tmp/pear/temp/redis/redis_session.c:482
#3  0x000055c094dabe87 in ?? ()
#4  0x000055c094dac78d in php_session_start ()
#5  0x000055c094dae0d5 in ?? ()
#6  0x00007fb41f351abd in xdebug_execute_internal (current_execute_data=0x7fb41f81b090, return_value=0x7fff5e50d540) at /tmp/pear/temp/xdebug/src/base/base.c:466
#7  0x000055c094f370c4 in ?? ()
#8  0x000055c094f9de47 in execute_ex ()
#9  0x00007fb41f35122d in xdebug_execute_ex (execute_data=0x7fb41f81b030) at /tmp/pear/temp/xdebug/src/base/base.c:380
#10 0x000055c094fa38b4 in zend_execute ()
#11 0x000055c094ef2a83 in zend_execute_scripts ()
#12 0x000055c094e8def8 in php_execute_script ()
#13 0x000055c094fa5c3f in ?? ()
#14 0x000055c094b551b9 in ?? ()
#15 0x00007fb426acf2e1 in __libc_start_main (main=0x55c094b54d50, argc=1, argv=0x7fff5e511058, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff5e511048) at ../csu/libc-start.c:291
#16 0x000055c094b552da in _start ()

Segfault appears to be from the strlen(persistent_id) line in redis_sock_create. Looks like the persistent_id pointer is pointing to invalid memory.

I've checked

  • [ x ] There is no similar issue from other users
  • [ x ] Issue isn't fixed in develop branch

Most helpful comment

Suspect that something like this will fix it:

diff --git a/redis_session.c b/redis_session.c
index 5428d52..e9cc41b 100644
--- a/redis_session.c
+++ b/redis_session.c
@@ -479,8 +479,9 @@ PS_OPEN_FUNC(redis)
                 addrlen = strlen(addr);
             }

-            redis_sock = redis_sock_create(addr, addrlen, port, timeout, read_timeout,
-                                           persistent, ZSTR_VAL(persistent_id), retry_interval);
+            char *persistent_id_strval = persistent_id ? ZSTR_VAL(persistent_id) : NULL;
+            redis_sock = redis_sock_create(addr, addrlen, port, timeout,
+                read_timeout, persistent, persistent_id_strval, retry_interval);

             redis_pool_add(pool, redis_sock, weight, db);
             redis_sock->prefix = prefix;

All 3 comments

Removing persistent=1 from the session.save_path avoids the segfault.

Suspect that something like this will fix it:

diff --git a/redis_session.c b/redis_session.c
index 5428d52..e9cc41b 100644
--- a/redis_session.c
+++ b/redis_session.c
@@ -479,8 +479,9 @@ PS_OPEN_FUNC(redis)
                 addrlen = strlen(addr);
             }

-            redis_sock = redis_sock_create(addr, addrlen, port, timeout, read_timeout,
-                                           persistent, ZSTR_VAL(persistent_id), retry_interval);
+            char *persistent_id_strval = persistent_id ? ZSTR_VAL(persistent_id) : NULL;
+            redis_sock = redis_sock_create(addr, addrlen, port, timeout,
+                read_timeout, persistent, persistent_id_strval, retry_interval);

             redis_pool_add(pool, redis_sock, weight, db);
             redis_sock->prefix = prefix;

Thank you for the report, it should be fixed via 149115e. I'll make sure we include this with 5.3.1 which will be very soon.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

namjitharavind picture namjitharavind  路  4Comments

danielignatius picture danielignatius  路  4Comments

RobChen picture RobChen  路  4Comments

LooLx picture LooLx  路  4Comments

galves picture galves  路  6Comments