# Bug #69127 session_regenerate_id(true) randomly generates a warning and loses session data

- Thread: https://externals.io/message/84096
- Original archive: https://news-web.php.net/php.internals/84096
- Started by Yasuo Ohgaki on 2015-03-01T04:53:30+00:00
- Messages: 12
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #84096 — Yasuo Ohgaki — 2015-03-01T04:53:30+00:00

URL: https://externals.io/message/84096#84096

Hi all,

There are too many things that I would like to improve ;)

https://bugs.php.net/bug.php?id=69127

This bug is known fatal bug for session module. I proposed "lazy_destroy"
to fix
this before, but it declined.

I think the name was wrong. With the proposal, session module destories
session data with lazy manner, but it's actually precise manner. i.e.
Session
module and browser is _not_ synced, so destroy must be done async manner
(~= lazy manner. For example, delete session data 60 seconds later).

The reason why session_regenerate_id(true) fails is it deletes session data
immediately even if session and browser is not in sync. Session and browser
cannot sync because there is no means in HTTP/Cookie.

Is there any other better idea for this?

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #84217 — Yasuo Ohgaki — 2015-03-03T07:25:13+00:00

URL: https://externals.io/message/84096#84217 · In reply to: #84096

Hi all,



>
>
> https://bugs.php.net/bug.php?id=69127
>
> This bug is known fatal bug for session module. I proposed "lazy_destroy"
> to fix
> this before, but it declined.
>
> I think the name was wrong. With the proposal, session module destories
> session data with lazy manner, but it's actually precise manner. i.e.
> Session
> module and browser is _not_ synced, so destroy must be done async manner
> (~= lazy manner. For example, delete session data 60 seconds later).
>
> The reason why session_regenerate_id(true) fails is it deletes session data
> immediately even if session and browser is not in sync. Session and browser
> cannot sync because there is no means in HTTP/Cookie.
>
> Is there any other better idea for this?
>

This is one of the most important problem for me.
Currently, session module is not working well enough as this bug report
shows.

If anyone do not come up with better idea, I would like to fix this by
deleting
old session data after certain amount of time.

Any ideas?

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #84225 — Andrey Andreev — 2015-03-03T10:40:41+00:00

URL: https://externals.io/message/84096#84225 · In reply to: #84217

Hi,


> Hi all,
>
> 
>
> > […]
>
> This is one of the most important problem for me.
> Currently, session module is not working well enough as this bug report
> shows.
>
> If anyone do not come up with better idea, I would like to fix this by
> deleting
> old session data after certain amount of time.
>
> Any ideas?
>

Why do you want to change it at all? If you don't want the data to get
immediately deleted, pass `FALSE` to the function and let the GC erase
it later.

Cheers,
Andrey.

---

## #84259 — Yasuo Ohgaki — 2015-03-03T18:21:37+00:00

URL: https://externals.io/message/84096#84259 · In reply to: #84225

Hi Andrey,



> Why do you want to change it at all? If you don't want the data to get
> immediately deleted, pass `FALSE` to the function and let the GC erase
> it later.
>

It's not precise at all. Old session data that must be deleted could exists
as long as it is accessed. i.e. Stolen session could exists as long as
attacker accesses it.

Timestamping is the method. It's the same as I proposed before.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #85171 — Yasuo Ohgaki — 2015-03-18T08:57:22+00:00

URL: https://externals.io/message/84096#85171 · In reply to: #84096

Hi all,



> https://bugs.php.net/bug.php?id=69127
>
> This bug is known fatal bug for session module. I proposed "lazy_destroy"
> to fix
> this before, but it declined.
>
> I think the name was wrong. With the proposal, session module destories
> session data with lazy manner, but it's actually precise manner. i.e.
> Session
> module and browser is _not_ synced, so destroy must be done async manner
> (~= lazy manner. For example, delete session data 60 seconds later).
>
> The reason why session_regenerate_id(true) fails is it deletes session
> data
> immediately even if session and browser is not in sync. Session and
> browser
> cannot sync because there is no means in HTTP/Cookie.
>
> Is there any other better idea for this?
>

I would like to fix this bug transparently. i.e. User cannot detect already
destroyed
session that is accessible.

The method is:

1. Add "__SESSION_TTL__", which has TTL timestamp, to $_SESSION hash before
serialization.
2. If session module finds "__SESSION_TTL__" in unserialized data and TTL
is past, then
regenerate session ID and create new session with empty data. (Old session
data is deleted actually)
3. If session is accessible by step 2, store TTL to PS(ttl) and initialize
$_SESSION without "__SESSION_TTL__".
4. If PS(ttl) has value greater than 0, add PS(ttl) back to session data
before serialization.

Note: Serialization/unserialization is done in session module. User cannot
know the existence.


I don't think users are using "__SESSION_TTL__" key for $_SESSION, but it
is possible.
If there is invalid "__SESSION_TTL__" in $_SESSION, raise `E_NOTICE` and
remove the key from
$_SESSION.

BC happens only when "__SESSION_TTL__" is used by users.

I would like to fix this in released versions, but it requires addition to
session module globals.
Fix will be only available to PHP7.

However, PS(ttl) can be added to the end of PS(). If this is OK, I'll fix
this bug from PHP 5.4.

Comments are appreciated.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #85254 — Yasuo Ohgaki — 2015-03-20T00:50:25+00:00

URL: https://externals.io/message/84096#85254 · In reply to: #84096

Hi all,



> There are too many things that I would like to improve ;)
>
> https://bugs.php.net/bug.php?id=69127
>
> This bug is known fatal bug for session module. I proposed "lazy_destroy"
> to fix
> this before, but it declined.
>
> I think the name was wrong. With the proposal, session module destories
> session data with lazy manner, but it's actually precise manner. i.e.
> Session
> module and browser is _not_ synced, so destroy must be done async manner
> (~= lazy manner. For example, delete session data 60 seconds later).
>
> The reason why session_regenerate_id(true) fails is it deletes session
> data
> immediately even if session and browser is not in sync. Session and
> browser
> cannot sync because there is no means in HTTP/Cookie.
>
> Is there any other better idea for this?
>

I've updated old RFC for this bug fix.

https://wiki.php.net/rfc/session_regenerate_id

I would like to start discussion shortly. If anyone would like to comment
now,
I appreciate it.

Thank you.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #85263 — Christoph Becker — 2015-03-20T02:53:40+00:00

URL: https://externals.io/message/84096#85263 · In reply to: #85254

Yasuo Ohgaki wrote:

> 
> 
> > […]
> 
> I've updated old RFC for this bug fix.
> 
> https://wiki.php.net/rfc/session_regenerate_id
> 
> I would like to start discussion shortly. If anyone would like to comment
> now,
> I appreciate it.

The RFC mentions PHP 7.0 as proposed PHP version.  Have you considered
the "PHP 7.0 timeline" RFC[1]?  As I understand it, any RFC put up to
vote after 2015-03-15 cannot target PHP 7.0.

Then again, if this will be considered a bug fix, an RFC would not be
necessary at all (if I'm not mistaken).

[1] <https://wiki.php.net/rfc/php7timeline>

-- 
Christoph M. Becker

---

## #85269 — Mateusz Kocielski — 2015-03-20T10:12:41+00:00

URL: https://externals.io/message/84096#85269 · In reply to: #85171

> I would like to fix this bug transparently. i.e. User cannot detect already
> destroyed
> session that is accessible.
> 
> The method is:
> 
> 1. Add "__SESSION_TTL__", which has TTL timestamp, to $_SESSION hash before
> serialization.
> 2. If session module finds "__SESSION_TTL__" in unserialized data and TTL
> is past, then
> regenerate session ID and create new session with empty data. (Old session
> data is deleted actually)
> 3. If session is accessible by step 2, store TTL to PS(ttl) and initialize
> $_SESSION without "__SESSION_TTL__".
> 4. If PS(ttl) has value greater than 0, add PS(ttl) back to session data
> before serialization.
> 
> Note: Serialization/unserialization is done in session module. User cannot
> know the existence.
> 
> 
> I don't think users are using "__SESSION_TTL__" key for $_SESSION, but it
> is possible.
> If there is invalid "__SESSION_TTL__" in $_SESSION, raise `E_NOTICE` and
> remove the key from
> $_SESSION.
> 
> BC happens only when "__SESSION_TTL__" is used by users.
> 
> I would like to fix this in released versions, but it requires addition to
> session module globals.
> Fix will be only available to PHP7.
> 
> However, PS(ttl) can be added to the end of PS(). If this is OK, I'll fix
> this bug from PHP 5.4.

Doh, it's happening again, it was discussed before. Anyway, your solution
seems to not fix the real problem behind the bug entry. I suspect that
following scenario may occur:

 http://lxr.php.net/xref/PHP_5_4/ext/session/mod_files.c#429

 scenario could be as follows:

 1. request A is done with sessid=123
 2. A calls session_regenerate_id and is preempted after unlink(2) but before
    access(2)
 3. request B is done with sessid=123 - session_start creates the session
 4. request A wakes up, session is written to fs by request B, so destroy
    fails

 Please note that if destroy fails, then new session is not generated,
possible (but ugly) solution is to call session_regenerate_id again.

 I didn't verify that, just guessing.

 Best Regards,
 Mateusz

---

## #85336 — Yasuo Ohgaki — 2015-03-20T21:28:31+00:00

URL: https://externals.io/message/84096#85336 · In reply to: #85263

Hi Christoph,

On Fri, Mar 20, 2015 at 11:53 AM, Christoph Becker <cmbecker69@gmx.de>
wrote:

> The RFC mentions PHP 7.0 as proposed PHP version.  Have you considered
> the "PHP 7.0 timeline" RFC[1]?  As I understand it, any RFC put up to
> vote after 2015-03-15 cannot target PHP 7.0.
>

This is usual bug fix.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #85341 — Yasuo Ohgaki — 2015-03-20T21:43:34+00:00

URL: https://externals.io/message/84096#85341 · In reply to: #85269

Hi Mateusz,

On Fri, Mar 20, 2015 at 7:12 PM, Mateusz Kocielski <shm@digitalsun.pl>
wrote:

> Doh, it's happening again, it was discussed before. Anyway, your solution
> seems to not fix the real problem behind the bug entry. I suspect that
> following scenario may occur:
>

Of course it was. I remember well.
Discussion was not going well because people does not understand
nature of web session. i.e. Session management is asynchronous.

It works almost always under stable network, but it cannot with unstable
network.


>
>  http://lxr.php.net/xref/PHP_5_4/ext/session/mod_files.c#429
>
>  scenario could be as follows:
>
>  1. request A is done with sessid=123
>  2. A calls session_regenerate_id and is preempted after unlink(2) but
> before
>     access(2)
>  3. request B is done with sessid=123 - session_start creates the session
>  4. request A wakes up, session is written to fs by request B, so destroy
>     fails
>
>  Please note that if destroy fails, then new session is not generated,
> possible (but ugly) solution is to call session_regenerate_id again.
>

It just does not work.
How do you keep session for lost session?

Lost session occurs like

1. Server executes session_regenerate_id(true), delete old data and send
    new session ID with copied data to browser.
2. Unstable network lost packet that sets new session ID.
3. Browser thinks old session ID is valid, but there is no session data for
it.

Besides, there is issue that session data must be deleted may keep alive
forever. Current session management is not predictable and precise at all.

If there is better idea other than the RFC, I appreciate it.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #85342 — Yasuo Ohgaki — 2015-03-20T21:49:43+00:00

URL: https://externals.io/message/84096#85342 · In reply to: #85341

Hi all,



> On Fri, Mar 20, 2015 at 7:12 PM, Mateusz Kocielski <shm@digitalsun.pl>
> wrote:
>
> > […]
>
> Of course it was. I remember well.
> Discussion was not going well because people does not understand
> nature of web session. i.e. Session management is asynchronous.
>
> It works almost always under stable network, but it cannot with unstable
> network.
>
>
> > […]
>
> It just does not work.
> How do you keep session for lost session?
>
> Lost session occurs like
>
> 1. Server executes session_regenerate_id(true), delete old data and send
>     new session ID with copied data to browser.
> 2. Unstable network lost packet that sets new session ID.
> 3. Browser thinks old session ID is valid, but there is no session data
> for it.
>
> Besides, there is issue that session data must be deleted may keep alive
> forever. Current session management is not predictable and precise at all.
>
> If there is better idea other than the RFC, I appreciate it.
>

BTW, if there are users who do not care about mobile devices at all, they
can simply set session.destroy_ttl=0.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #85345 — Yasuo Ohgaki — 2015-03-20T22:12:32+00:00

URL: https://externals.io/message/84096#85345 · In reply to: #85341

Hi all,



>  Please note that if destroy fails, then new session is not generated,
> > […]
>
> It just does not work.
> How do you keep session for lost session?
>
> Lost session occurs like
>
> 1. Server executes session_regenerate_id(true), delete old data and send
>     new session ID with copied data to browser.
> 2. Unstable network lost packet that sets new session ID.
> 3. Browser thinks old session ID is valid, but there is no session data
> for it.
>
> Besides, there is issue that session data must be deleted may keep alive
> forever. Current session management is not predictable and precise at all.
>
> If there is better idea other than the RFC, I appreciate it.
>

One more additional note.

Databases use 2 phase commit to synchronize multiple databases. Similar
method cannot be used because HTTP is stateless. i.e. Connections are
closed. Even with HTTP/2, user may have multiple independent connections,
i.e. multiple tabs, and there is no lock mechanism. It just cannot work.
Therefore, 2 phase commit cannot be used.

I cannot think of perfect locking mechanism that synchronize server and
browser.
i.e. Locking can be done by using additional cookie, but I cannot make sure
browsers has synchronized time.  If there is reliable locking, synchronous
session management can be done. Even if there is, it would cost too much.
e.g. Time consuming and too complex for the purpose.

Ideas are appreciated.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net
