Bug 1419736
| Summary: | 32-bit stat returns wrong st_mtime if file timestamp does not fit in 32 bits | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Paul Eggert <eggert> | ||||
| Component: | kernel | Assignee: | Carlos O'Donell <codonell> | ||||
| Status: | NEW --- | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | ||||
| Severity: | unspecified | Docs Contact: | |||||
| Priority: | unspecified | ||||||
| Version: | rawhide | CC: | arjun, codonell, cz172638, dj, eggert, fweimer, gansalmon, ichavero, itamar, jonathan, kernel-maint, law, madhu.chinakonda, mchehab, mfabian, pfrankli, siddhesh, yselkowi | ||||
| Target Milestone: | --- | ||||||
| Target Release: | --- | ||||||
| Hardware: | x86_64 | ||||||
| OS: | Linux | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | Doc Type: | If docs needed, set a value | |||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | Type: | Bug | |||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Attachments: |
|
||||||
|
Description
Paul Eggert
2017-02-06 22:41:04 UTC
Unfortunately the issue is not as simple as a black and white overflow check. Firstly the overflow has to be applied to all 'struct timespec' used in all stat-like interfaces. That is quite a lot of new code in the hot path to catch only cases where it's <1901 or >2038. Therefore glibc and I believe the linux kernel are still debating on the issue of fixing time overflow issues for 32-bit applications (see 'Debatable' in the wiki link below), instead the suggested solution will be to recompile the application using 64-bit time. Please see "Y2038 Proofness Design" for a broad discussion of this problem and solution: https://sourceware.org/glibc/wiki/Y2038ProofnessDesign In this particular case there is nothing that glibc can do. We are calling the stat64 syscall, which is all the 32-bit process has available, and it returns already overflowed 32-bit struct timespec values. The 32-bit application doesn't have access to the 64-bit struct timespec from the struct kstat the 64-bit kernel uses internally. The stat64 API was designed to support larger file-related attributes, but not a larger 64-bit time. In summary: - As of today cannot represent time outside of 1901<->2038 for 32-bit applications using non-Y2038-proof APIs that have non-Y2038-proof types. - There is no forthcoming fix other than to use 64-bit applications. - The future fix is to recompile your 32-bit application with 64-bit time support. Does that answer your question Paul? (In reply to Carlos O'Donell from comment #1) > In this particular case there is nothing that glibc can do. Thanks for the explanation. This bug should not be filed under 'glibc', then. I'll try to change its component to 'kernel'. > Does that answer your question Paul? Yes, thanks, though perhaps this bug's priority needs tweaking. True, we have until January 2038 before calls like 'time ()' stop working, and it'll be unlikely for 32-bit apps to run across naturally-occurring out-of-range file timestamps before then. However, we may need to worry about malicious attacks on 32-bit applications based on their mishandling of out-of-range file timestamps. (In reply to Paul Eggert from comment #2) > (In reply to Carlos O'Donell from comment #1) > > In this particular case there is nothing that glibc can do. > > Thanks for the explanation. This bug should not be filed under 'glibc', > then. I'll try to change its component to 'kernel'. While at the highest level of abstraction it is debatable if the 32-bit APIs should be fixed, this particular case is solvable. On a case-by-case basis I think we can discuss EOVERFLOW checking and returns. In the particular case of stat64, which is implemented by x86-specific code, this certainly needs fixing in the kernel to return EOVERFLOW. e.g. arch/x86/ia32/sys_ia32.c 66 /* 67 * Another set for IA32/LFS -- x86_64 struct stat is different due to 68 * support for 64bit inode numbers. 69 */ 70 static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat) 71 { 72 typeof(ubuf->st_uid) uid = 0; 73 typeof(ubuf->st_gid) gid = 0; 74 SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid)); 75 SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid)); 76 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) || 77 __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) || 78 __put_user(stat->ino, &ubuf->__st_ino) || 79 __put_user(stat->ino, &ubuf->st_ino) || 80 __put_user(stat->mode, &ubuf->st_mode) || 81 __put_user(stat->nlink, &ubuf->st_nlink) || 82 __put_user(uid, &ubuf->st_uid) || 83 __put_user(gid, &ubuf->st_gid) || 84 __put_user(huge_encode_dev(stat->rdev), &ubuf->st_rdev) || 85 __put_user(stat->size, &ubuf->st_size) || ~~~ 86 __put_user(stat->atime.tv_sec, &ubuf->st_atime) || 87 __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec) || 88 __put_user(stat->mtime.tv_sec, &ubuf->st_mtime) || 89 __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) || 90 __put_user(stat->ctime.tv_sec, &ubuf->st_ctime) || 91 __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) || ~~~ All three of these struct timespecs would need independent conversion with overflow checks. 92 __put_user(stat->blksize, &ubuf->st_blksize) || 93 __put_user(stat->blocks, &ubuf->st_blocks)) 94 return -EFAULT; 95 return 0; 96 } > > Does that answer your question Paul? > > Yes, thanks, though perhaps this bug's priority needs tweaking. True, we > have until January 2038 before calls like 'time ()' stop working, and it'll > be unlikely for 32-bit apps to run across naturally-occurring out-of-range > file timestamps before then. However, we may need to worry about malicious > attacks on 32-bit applications based on their mishandling of out-of-range > file timestamps. We _do not_ have until 2038, in fact we probably have only a 5 year window remaining to fix this issue. Given the 10-year timelines for enterprise adoption and support, and a desire to see this kind of fix land earlier than that window, we probably need a good 15-year lead on the problem. Worse is that IoT deployments on cheap 32-bit hardware are going to need 64-bit time also. (In reply to Carlos O'Donell from comment #3) > We _do not_ have until 2038, in fact we probably have only a 5 year window > remaining to fix this issue. Given the 10-year timelines for enterprise > adoption and support, and a desire to see this kind of fix land earlier than > that window, we probably need a good 15-year lead on the problem. Worse is > that IoT deployments on cheap 32-bit hardware are going to need 64-bit time > also. To be absolutely clear, nothing in this paragraph should be read as a commitment for any future enterprise distribution to continue to support running legacy 32-bit binaries, with a 32-bit time_t type or a 64-bit time_t type. (In reply to Florian Weimer from comment #4) > (In reply to Carlos O'Donell from comment #3) > > We _do not_ have until 2038, in fact we probably have only a 5 year window > > remaining to fix this issue. Given the 10-year timelines for enterprise > > adoption and support, and a desire to see this kind of fix land earlier than > > that window, we probably need a good 15-year lead on the problem. Worse is > > that IoT deployments on cheap 32-bit hardware are going to need 64-bit time > > also. > > To be absolutely clear, nothing in this paragraph should be read as a > commitment for any future enterprise distribution to continue to support > running legacy 32-bit binaries, with a 32-bit time_t type or a 64-bit time_t > type. Absolutely. My intent was to clarify that upstream has a shorter timeframe than 20 years. Particularly if upstream wishes to support downstreams that make a decision to continue to support running 32-bit binaries. This is better tracked on rawhide than F25. There's been ongoing work in the kernel for Y2038. What kernel versions have you verified this bug on? (In reply to Laura Abbott from comment #6) > This is better tracked on rawhide than F25. There's been ongoing work in the > kernel for Y2038. What kernel versions have you verified this bug on? I've verified on 4.8.15-300.fc25.x86_64+debug. But upstream 4.10.0-rc7 still has the same code in cp_stat64() which doesn't check for overflows. > What kernel versions have you verified this bug on?
I verified it just now on 4.9.9-200.fc25.x86_64, the current Fedora 25 kernel.
(In reply to Carlos O'Donell from comment #7) > I've verified on 4.8.15-300.fc25.x86_64+debug. But upstream 4.10.0-rc7 still > has the same code in cp_stat64() which doesn't check for overflows. If I'm reading the kernel right, the problem is also in cp_new_stat, cp_new_stat64, cp_statx, and cp_compat_stat. (Not that I'm much of a kernel hacker.) Is there some way to boost the priority of this bug? As you say, it needs to be fixed reasonably soon if we're going to fix it at all. I'm writing now because a new gzip bug report about the issue came in here: https://bugs.gnu.org/29033#8 While checking out the new bug report, I verified that the kernel bug is still in 4.13.10-200.fc26.x86_64, the current Fedora 26 kernel. (In reply to Paul Eggert from comment #9) > Is there some way to boost the priority of this bug? You need to report it upstream. Probably send mail to Alexander Viro <viro.org.uk>, David Howells <dhowells> (who added statx) and Cc: linux-fsdevel.org. Perhaps Cc: Eric Biggers <ebiggers> as well. (In reply to Florian Weimer from comment #10) > You need to report it upstream. Thanks, I sent it as you suggested, archived here: https://marc.info/?l=linux-fsdevel&m=150991765312229 |