Re: Possible bug in NFSv4 with krb5p security?
On Wed, Feb 20, 2013 at 06:29:07PM -0500, Rick Macklem wrote: Andrey Simonnenko wrote: Another variant. This is a program that can be used for verifying correctness of the function, just change PWBUF_SIZE_* values and put some printfs to see when buffer is reallocated. sizehint is updated only when malloc() succeeded. - static int getpwnam_r_func(const char *name, uid_t *uidp) { #define PWBUF_SIZE_INI (2 * MAXLOGNAME + MAXPATHLEN + _PASSWORD_LEN) #define PWBUF_SIZE_INC 128 static size_t sizehint = PWBUF_SIZE_INI; struct passwd pwd; struct passwd *pw; char *buf; size_t size; int error; char lname[MAXLOGNAME]; char bufs[PWBUF_SIZE_INI]; strncpy(lname, name, sizeof(lname)); buf = bufs; size = sizeof(bufs); for (;;) { error = getpwnam_r(lname, pwd, buf, size, pw); if (buf != bufs) free(buf); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else if (error != ERANGE || size SIZE_MAX - PWBUF_SIZE_INC) return (GSS_S_FAILURE); if (size != sizehint) size = sizehint; else size += PWBUF_SIZE_INC; buf = malloc(size); if (buf == NULL) return (GSS_S_FAILURE); sizehint = size; } } All looks fine to me. (Before my mailer messed with the whitespace;-) Thanks, rick ps: I will commit it in April, unless someone else does so sooner. I was thinking about this approach once again and made a conclusion that it is wrong. Using static buffer at first and then allocate memory for next calls can cause slowdown, depends on number of entries and used database backend of course. The libc code for getpwnam() allocates memory for the buffer and does not free it on exit from the function, If the above written code or any of its modification is going to be committed to the source base (by you or by some another committer), then I ask and require to not write/mention my name and email address neither in source file nor in commit log message. Appropriate commit log message for the above written code can be the following: -- Since FreeBSD does not support sysconf(_SC_GETPW_R_SIZE_MAX), then allocate a buffer of sufficient size for getpwnam_r() as it is suggested in EXAMPLES of SUSv4 documentation for the getpwnam_r() function. -- since this documentation has similar code. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: Possible bug in NFSv4 with krb5p security?
On Tue, Feb 19, 2013 at 08:52:49PM -0500, Rick Macklem wrote: I cannot find how to get information about maximum buffer size for the getpwnam_r() function. This information should be returned by sysconf(_SC_GETPW_R_SIZE_MAX), but since it does not work on FreeBSD it is necessary to guess its size. Original value is 128 and it works for somebody, 1024 works for your environment, but it can fail for another environment. SUSv4 specifies Storage referenced by the structure is allocated from the memory provided with the buffer parameter, but then tells about groups in EXAMPLE for getpwnam_r() Note that sysconf(_SC_GETPW_R_SIZE_MAX) may return -1 if there is no hard limit on the size of the buffer needed to store all the groups returned. malloc() can give overhead, but that function can try to call getpwnam_r() with buffer allocated from stack and if getpwnam_r() failed with ERANGE use dynamically allocated buffer. #define PWBUF_SIZE_INI (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) #define PWBUF_SIZE_INC 128 char bufs[2 * MAXLOGNAME + MAXPATHLEN + PASSWORD_LEN + 1 + 32]; error = getpwnam_r(lname, pwd, bufs, sizeof(bufs), pw); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else if (error != ERANGE) return (GSS_S_FAILURE); size = PWBUF_SIZE_INI; for (;;) { size += PWBUF_SIZE_INC; buf = malloc(size); if (buf == NULL) return (GSS_S_FAILURE); error = getpwnam_r(lname, pwd, buf, size, pw); free(buf); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else { if (error == ERANGE size = SIZE_MAX - PWBUF_SIZE_INC) continue; return (GSS_S_FAILURE); } } Just my opinion, but I think the above is a good approach. (ie. First trying a fairly large buffer on the stack that will succeed 99.99% of the time, but check for ERANGE and loop trying progressively larger malloc'd buffers until it stops reporting ERANGE.) I suspect the overheads behind getpwnam_r() are larger than the difference between using a buffer on the stack vs malloc, so I think it should use a fairly large buffer the first time. Personally, I might have coded it as a single do { } while(), with the first attempt in it, but that's just personal stylistic taste. (You can check for buf != bufs before doing a free() of it.) And, if you wanted to be clever, the code could use a static bufsiz_hint, which is set to the largest size needed sofar and that is used as the initial malloc size. That way it wouldn't loop as much for a site with huge passwd entries. (An entire bio in the GECOS field or ???) Thanks for the review. Another variant. This is a program that can be used for verifying correctness of the function, just change PWBUF_SIZE_* values and put some printfs to see when buffer is reallocated. sizehint is updated only when malloc() succeeded. - #include sys/param.h #include sys/limits.h #include gssapi/gssapi.h #include errno.h #include limits.h #include pwd.h #include stdio.h #include stdlib.h #include string.h #include unistd.h static int getpwnam_r_func(const char *name, uid_t *uidp) { #define PWBUF_SIZE_INI (2 * MAXLOGNAME + MAXPATHLEN + _PASSWORD_LEN) #define PWBUF_SIZE_INC 128 static size_t sizehint = PWBUF_SIZE_INI; struct passwd pwd; struct passwd *pw; char *buf; size_t size; int error; char lname[MAXLOGNAME]; char bufs[PWBUF_SIZE_INI]; strncpy(lname, name, sizeof(lname)); buf = bufs; size = sizeof(bufs); for (;;) { error = getpwnam_r(lname, pwd, buf, size, pw); if (buf != bufs) free(buf); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else if (error != ERANGE || size SIZE_MAX - PWBUF_SIZE_INC) return (GSS_S_FAILURE); if (size != sizehint) size = sizehint; else size += PWBUF_SIZE_INC; buf = malloc(size); if (buf == NULL) return (GSS_S_FAILURE); sizehint = size; } } int main(void) { const char *str[] = { man, root, q, bin, NULL }; uid_t uid; u_int i; for (i = 0; str[i] != NULL; ++i) { printf(%-20s\t, str[i]); if (getpwnam_r_func(str[i], uid) == GSS_S_COMPLETE) printf(%u\n, uid); else printf(not found\n); } return (0); } - ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to
Re: Possible bug in NFSv4 with krb5p security?
On Tue, Feb 19, 2013 at 12:06:13AM +0800, Elias Martenson wrote: You were right, the problem was in pname_to_uid.c. In it, the following code can be found: char lname[MAXLOGNAME + 1], buf[1024]; /* some code snipped for brevity... */ getpwnam_r(lname, pwd, buf, sizeof(buf), pw); if (pw) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else { return (GSS_S_FAILURE); } As it turns out, the getpwnam_r() call fails with ERANGE (I had to check the return value from getpwnam_r() in order to determine this, as pw is set to NULL both if there was an error or if the user name can't be found). Now, increasing the size of buf to 1024 solved the problem, and now the lookup works correctly. I wrote a small test program that issued the same call to getpwnam_r() and it worked. Until I su'ed to root, and then it failed. It seems as though the buffer needs to be bigger if you're root. I have no idea why, but there you have it. Problem solved. It can require bigger buffer, since root can get the pw_password field in the struct passwd{}. Since sysconf(_SC_GETPW_R_SIZE_MAX) does not work on FreeBSD, the buffer for getpwnam_r() call should have at least (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) bytes (it is unclear how much is required for pw_gecos). This buffer can be dynamically reallocated until getpwnam_r() is not return ERANGE error (the following code has not been compiled and verified): #define PWBUF_SIZE_INI (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) #define PWBUF_SIZE_INC 128 size = PWBUF_SIZE_INI; for (;;) { size += PWBUF_SIZE_INC; buf = malloc(size); if (buf == NULL) return (GSS_S_FAILURE); error = getpwnam_r(lname, pwd, buf, size, pw); free(buf); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else { if (error == ERANGE size = SIZE_MAX - PWBUF_SIZE_INC) continue; return (GSS_S_FAILURE); } } ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: Possible bug in NFSv4 with krb5p security?
On Tue, Feb 19, 2013 at 05:35:50PM +0800, Elias Martenson wrote: On 19 February 2013 17:31, Andrey Simonenko si...@comsys.ntu-kpi.kiev.uawrote: It can require bigger buffer, since root can get the pw_password field in the struct passwd{}. Since sysconf(_SC_GETPW_R_SIZE_MAX) does not work on FreeBSD, the buffer for getpwnam_r() call should have at least (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) bytes (it is unclear how much is required for pw_gecos). This buffer can be dynamically reallocated until getpwnam_r() is not return ERANGE error (the following code has not been compiled and verified): Is this really a better solution than to aim high right away? A series of malloc() calls should certainly have much higher overhead than the previous stack-allocated solution. A better compromise would be to do the lookup in a separate function, that allocates the buffer using alloca() instead, yes? I cannot find how to get information about maximum buffer size for the getpwnam_r() function. This information should be returned by sysconf(_SC_GETPW_R_SIZE_MAX), but since it does not work on FreeBSD it is necessary to guess its size. Original value is 128 and it works for somebody, 1024 works for your environment, but it can fail for another environment. SUSv4 specifies Storage referenced by the structure is allocated from the memory provided with the buffer parameter, but then tells about groups in EXAMPLE for getpwnam_r() Note that sysconf(_SC_GETPW_R_SIZE_MAX) may return -1 if there is no hard limit on the size of the buffer needed to store all the groups returned. malloc() can give overhead, but that function can try to call getpwnam_r() with buffer allocated from stack and if getpwnam_r() failed with ERANGE use dynamically allocated buffer. #define PWBUF_SIZE_INI (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) #define PWBUF_SIZE_INC 128 char bufs[2 * MAXLOGNAME + MAXPATHLEN + PASSWORD_LEN + 1 + 32]; error = getpwnam_r(lname, pwd, bufs, sizeof(bufs), pw); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else if (error != ERANGE) return (GSS_S_FAILURE); size = PWBUF_SIZE_INI; for (;;) { size += PWBUF_SIZE_INC; buf = malloc(size); if (buf == NULL) return (GSS_S_FAILURE); error = getpwnam_r(lname, pwd, buf, size, pw); free(buf); if (pw != NULL) { *uidp = pw-pw_uid; return (GSS_S_COMPLETE); } else { if (error == ERANGE size = SIZE_MAX - PWBUF_SIZE_INC) continue; return (GSS_S_FAILURE); } } ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: [CFT] Some updates to libc/rpc (second try)
On Thu, Aug 30, 2012 at 02:37:17AM -0700, Garrett Cooper wrote: Detailed description of mistakes in these files and correct implementation: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/165710 A developer at $work (Isilon) developed a slightly simpler patch than that based on our custom 7.x sources recently to deal with concurrency issues in netconfig. I'll talk with a couple people to see whether or not the solution can be contributed back [after some polishing -- maybe -- and further testing]. Can you post changes and corrected bugs in getnetconfig.c and getnetpath.c in your (your $work) implementation. This is the list of changes and corrected bugs in my implementation: 1. __nc_error() does not check return value from malloc() and can pass NULL pointer to thr_setspecific(). 2. setnetconfig() has a race condition with reference counter when several threads call this function and only one thread successfully opened database file, while other threads failed in this function. If that one thread called endnetconfig(), then it can keep cached data in memory, but all threads will not have opened handles. 3. getnetconfig() should return entries from /etc/netconfig file in the same order as they are specified according to netconfig(5). If several threads call getnetconfig() using different handlers, then entries for each handler will be returned in random order. 4. getnetconfig() has a race condition that can cause NULL pointer dereference when several threads call this function using one handler. 5. getnetconfig() allows to continue to get entries if database file has invalid format, because it does not remember previous state. 6. endnetconfig() has a race condition with reference count and can keep cached data, while all handlers are closed. 7. getnetconfigent() uses getnetconfig() and has the same mistakes, also this function duplicates code from getnetconfig(). 8. getnetconfig() and getnetconfigent() use too much memory for entry data, each entry require ~1 kbytes of memory, while usually only 50 bytes is needed. 9. parse_ncp() incorrectly parses flags in netconfig entry and allows wrong combinations of flags, it does not allow spaces before entry, does not check number of elements in each netconfig entry, does not allow empty lines. 10. nc_sperror() is not optimal. 11. dup_ncp() is not optimal, allocates more memory than was used in the original structure, call strcpy() several times instead of calling memcpy() one time. 12. setnetpath() is not optimal, e.g. it calls setnetconfig() and then calls endnetconfig(). 13. getnetpath() uses getnetconfig() and getnetconfigent() and has the same mistakes. 14. getnetpath() has race conditions when several threads call this function using one handler, as a result there are memory leaks and not synchronized access with modifications to data if the NETPATH environment variable is set. 15. _get_next_token() is too complex, incorrectly understand \-sequences. 16. All functions do not specify error code in all possible cases, so nc_sperror() and nc_perror() functions are useless. Difference between netconfig.c vs getnetconfig.c and getnetpath.c: 1. __nc_error() was corrected, but its implementation is the same, this is a standard implementation for thread-specific data handling. nc_perror() was taken from getnetconfig.c, it cannot be written in other way. 2. Some errors messages were taken from getnetconfig.c. 3. New nc_parse() (old parse_ncp()) was corrected and optimized a bit, it just parses white space separated fields in a string. 4. Some variables and macro variables names were taken from getnetconfig.c. 5. All other functions and data structures were rewritten. Additionally I corrected libc/include/reentrant.h, getnetconfig.3, and getnetpath.3. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: [CFT] Some updates to libc/rpc (second try)
On Fri, Aug 31, 2012 at 08:12:09AM -0400, John Baldwin wrote: On Friday, August 31, 2012 7:06:53 am Andrey Simonenko wrote: On Thu, Aug 30, 2012 at 02:37:17AM -0700, Garrett Cooper wrote: Detailed description of mistakes in these files and correct implementation: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/165710 A developer at $work (Isilon) developed a slightly simpler patch than that based on our custom 7.x sources recently to deal with concurrency issues in netconfig. I'll talk with a couple people to see whether or not the solution can be contributed back [after some polishing -- maybe -- and further testing]. Can you post changes and corrected bugs in getnetconfig.c and getnetpath.c in your (your $work) implementation. There is a thread on threads@ with patches to make the API thread-safe that I believe came from Isilon. It was posted in the last week or so, so it should be easy to find in the archives. Thank you for this information. I checked the logic of their changes. Making all data per-thread is wrong from my point of view. 1. Several threads can call getnetconfig() using the same handler obtained by setnetconfig(). If each thread has own FILE pointer, then some getnetconfig() will crash a program since fgets() will be called for NULL FILE pointer. 2. One thread can get handler by setnetconfig() and pass this handler to another thread and getnetconfig() will crash a program. This is the similar mistake, but getnetconfig() is not called in parallel. 3. Each thread has to open netconfig(5) database, parse its content every time for each getnetconfig() call since data is not cached. This is slow. There is one per-thread value, it is error code of the last failed function, this value cannot be kept in handler, since nc_perror() and nc_sperror() do not have handler argument. Since printing error is expected in the same thread when getnetconfig() failed (for example), I think this is Ok. If error is print in another thread, then we simply will not see correct error message, but program will not be crashed. I just commented only per-thread idea of data in getnetconfig.c, I do not compare my implementation, since their patch does not correct any other mistake described and corrected in my PR. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: [CFT] Some updates to libc/rpc (second try)
On Wed, Aug 29, 2012 at 09:57:37PM -0500, Pedro Giffuni wrote: This is rather critical stuff (libc) so I have no hurry and would like extensive testing before considering it for head. Please give it a try and report any issue. Looks like that their getnetconfig.c and getnetpath.c have similar mistakes as these files have in FreeBSD. Detailed description of mistakes in these files and correct implementation: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/165710 Related PR: http://www.freebsd.org/cgi/query-pr.cgi?pr=79683 ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Comparison of the nfse compatibility mode with mountd and exports(5)
On Sat, Jun 30, 2012 at 08:53:09PM -0400, Rick Macklem wrote: I haven't looked at Andrey's patch, but conceptually it sounds like the best approach. As I understand it, the problem with replacing mountd with nfse (at least in the FreeBSD source tree) is that nfse is not 100% backwards compatible with /etc/exports and, as such, is a POLA violation. Since NFSE was mentioned in this thread and there were some opinions about its compatibility with existent NFS exports configuration, I made comparison of the nfse compatibility mode with mountd and exports(5): http://nfse.sourceforge.net/COMPATIBILITY ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: Occassional permission denied in the middle of a large transfer over NFS
This message contains only corrections to typos from my previous message. On Mon, Jul 09, 2012 at 12:44:56PM +0300, Andrey Simonenko wrote: Here -alldirs means that /cdrom should be a file system. As I remember this even worked before revision 1.85 of mountd/mountd.c, then mountd.c began to use nmount(2). Now if one puts /cdrom in /etc/exports and ^^\ /cdrom -alldirs Let's consider the same example but without the -alldirs options: /usr/local/export -maproot=root 1.2.3.4 3. nfse in the native mode will export /usr if it is or will be a mount point: \ /usr/local/export ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: Occassional permission denied in the middle of a large transfer over NFS
Hello again, On Sun, Jul 08, 2012 at 06:35:50PM +0100, Vincent Hoffman wrote: Replying to myself just as a record, I have tried nfse and I didnt get the permission denied at all. The only issue I had with it is that it strictly adheres to the syntax in exports(5) while mountd is a little more flexible. I had /usr/local/export -alldirs -maproot=root 85.xx.xx.xx /usr is the root of that filesystem mountd - allowed this but actually silently exports /usr (and all dirs below) nfse - didnt allow this, it needed to be the correct /usr -alldirs -maproot=root 85.xx.xx.xx which is I guess a POLA violation but follows the documentation. this was using nfse in mountd compatibility mode. I havent played with its more advanced features. The -alldirs option in the exports(5) file does not mean only all directories. Please read these lines from exports(5) DESCRIPTION: The second is to specify the pathname of the root of the file system fol- lowed by the -alldirs flag; this form allows the host(s) to mount at any point within the file system, including regular files if the -r option is used on mountd(8). The -alldirs option specifies that this pathname must be the root (mount point) of some file system. And read these lines from EXAMPLES: The file system rooted at /cdrom will be exported read-only to the entire network 192.168.33.0/24, including all its subdirectories. Since /cdrom is the conventional mountpoint for a CD-ROM device, this export will fail if no CD-ROM medium is currently mounted there since that line would then attempt to export a subdirectory of the root file system with the -alldirs option which is not allowed. The -quiet option will then sup- press the error message for this condition that would normally be sys- logged. As soon as an actual CD-ROM is going to be mounted, mount(8) will notify mountd(8) about this situation, and the /cdrom file system will be exported as intended. Note that without using the -alldirs option, the export would always succeed. While there is no CD-ROM medium mounted under /cdrom, it would export the (normally empty) directory /cdrom of the root file system instead. Here -alldirs means that /cdrom should be a file system. As I remember this even worked before revision 1.85 of mountd/mountd.c, then mountd.c began to use nmount(2). Now if one puts /cdrom in /etc/exports and there is no file system mounted on /cdrom, then the entire / will be exported. Just create /etc/exports with one line /cdrom -alldirs and try to mount server:/ on another system, you will get access to the / of the server. The current version of mountd is not little more flexible, it does not follow traditional -alldirs option's logic and does not follow description of the -alldirs option in the exports(5) manual page, I guess this is a POLA violation. Now let's back to your example where /usr is the root of the file system: /usr/local/export -alldirs -maproot=root 1.2.3.4 1. mountd exports /usr and all subdirectories under it for NFSv2/3 clients. Actually it has to export /usr/local/export only and all subdirectories under it only if /usr/local/export is or will be the root of some file system. 2. nfse in the compatibility mode sees that there is the -alldirs option and will export /usr/local/export and all subdirectories under it only if /usr/local/exports is or will be the root of some file system. If one runs nfse -Ct ... for this file then its output will be: configure: reading file /etc/exports configure: converting configuration to native format Pathname /usr/local/export Export specifications: -rw -sec sys -maproot 0:0:5 -host 1.2.3.4 Subdirectories for NFSv2/3: /usr/local/export -alldirs -host 1.2.3.4 Warning: subdirectories exports are insecure This is output in nfse native format. Using NFSE part in the kernel, nfse verifies whether /usr/local/export is a mount point, whether file system supports NFS, and only if everything is correct, it starts to export it. When file system is unmounted or when another file system is mounted, then NFSE part in the kernel is informed by EVENTHANDLERs vfs_mount_event/vfs_unmount_event and NFS server verifies whether it still can export this file system (it can be unmounted or it can be shadowed). The userland utility nfse got information of VFS events via kevents VQ_MOUNT/VQ_UNMOUNT and only the verifies using NFSE part in the kernel whether some file system is still exported or can become exported. There is one implementation mistake when nfse -C ... is used. The nfse utility follows implementation mistake from mountd and verifies what is a file system and what is not a file system using the f_mntonname field in the struct mount{}. This is wrong since parts of mount point directory can be renamed and this is not reflected in the f_mntonname value. That's why I do not
Re: Occassional permission denied in the middle of a large transfer over NFS
On Sun, Jul 08, 2012 at 07:48:11PM -0400, Rick Macklem wrote: Replying to myself just as a record, I have tried nfse and I didnt get the permission denied at all. The only issue I had with it is that it strictly adheres to the syntax in exports(5) while mountd is a little more flexible. I had /usr/local/export -alldirs -maproot=root 85.xx.xx.xx /usr is the root of that filesystem mountd - allowed this but actually silently exports /usr (and all dirs below) Not exactly correct. mountd exports the entire file system in the kernel for the NFS server, since exports can only be attached to the mount points in the kernel. However, when the client's mount protocol requests a mount file handle for anything other than /usr/local/export, it will refuse that. (Which means that to mount anything other than /usr/local/export, the client must maliciously guess the file handle for mounting.) Put another way, a non-malicious NFSv3 client will only be able to mount /usr/local/export. Robert Watson calls this an administrative control and feels that it is necessary. According to the exports(5) manual page and this example (/usr is the mount point and the -alldir option is given), this example means the following: export /usr/local/export only if it is or will be a mount point and administratively export all subdirectories under it for NFSv2/3 clients. Good description of the -alldirs option is given in the EXAMPLES section from exports(5) in paragraph about /cdrom -alldirs. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: Occassional permission denied in the middle of a large transfer over NFS
On Sun, Jul 01, 2012 at 12:13:30PM +0100, Vincent Hoffman wrote: On 01/07/2012 01:53, Rick Macklem wrote: I haven't looked at Andrey's patch, but conceptually it sounds like the best approach. As I understand it, the problem with replacing mountd with nfse (at least in the FreeBSD source tree) is that nfse is not 100% backwards compatible with /etc/exports and, as such, is a POLA violation. Understood. Its far from a simple drop in replacement. List of difference between nfse -C ... (compatible mode with mountd) and mountd is given here: http://lists.freebsd.org/pipermail/freebsd-fs/2012-June/014554.html If we ignore absence of some obsolete options support and some command line options, the rest of differences visible to a user will occur only if one does not follow rules of exports(5) file format. The native mode of nfse (nfs.exports(5) file format) is different than the logic of mountd, just because using existent exports(5) file format it is impossible to specify export of not mounted file system, it is impossible to specify all export settings for one file system in one line, etc. Can you verify whether nfse compatible mode with mountd is really compatible with exports(5) files on your systems using instructions from this message (no installation or patching is required): http://lists.freebsd.org/pipermail/freebsd-fs/2010-May/008421.html ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: mountd, rpc.lockd and rpc.statd patches for testing
On Thu, Apr 19, 2012 at 08:44:37PM -0400, Rick Macklem wrote: Andrey Simonenko wrote: On Mon, May 30, 2011 at 04:56:02PM -0400, Rick Macklem wrote: Hi, I have patches for the mountd, rpc.statd and rpc.lockd daemons that are meant to keep them from failing when a dynamically selected port# is not available for some combination of udp,tcp X ipv4,ipv6 If anyone would like to test these patches, they can be found at: http://people.freebsd.org/~rmacklem/mountd.patch statd.patch lockd.patch Although I think I got them correct, they are rather big and ugly. I have checked this update for mountd in 10-CURRENT and has two questions: 1. What is the sense to try to use the same port number for all supported netconfigs if specific port number is not given in a command line option? Well, there was a discussion of this on one of the mailing lists at the time. I started with a much simpler patch that didn't try and make all 4 udp/tcp, ip4/ip6 combinations use the same port#, but others felt that was important. (Something about tracking what port# were in use, but I can't quite recall. If you want to know the reasoning, look for the thread that would have been shortly before the commit.) I verified how mountd, rpc.lockd and rpc.statd worked on previous version of FreeBSD. On 6.2-PRERELEASE mountd, rpc.lockd and rpc.statd did not have the -h option and all these programs used random port numbers for all netconfigs. When the -h option was added to mountd, rpc.lockd and rpc.statd this logic was changed and random port was used for all netconfigs and for all IP address if they are specified. Obviously everyone who used NFS after these changes got non working NFS several times even for configurations without the -h option. rpcbind(8) in FreeBSD does not allow multiple settings for the same network ID, so wildcard address for each netconfig should be used. As I understand this is a design decision and multiple settings for one RPC service are refused in rpcbind/rpcb_svc_com.c:map_set(). Would all possible cases be checked before commiting support for the -h option, may be that option and broken logic will not appear in mountd, rpc.lockd and rpc.statd. Now, everything works, but mountd still can fail during startup (depends on activity of other network programs of course). One comment for netconfig related functions usage. Each setnetconfig() call allocates memory and depending on implementation can use other resources, so endnetconfig() should be called before reusing netconfig handle. _ Ok, I'll take a look someday. Since it happens a finite number of times, any leak should be bounded and, as such, shouldn't cause serious problems. However, I wasn't aware of the above and it should be fixed. When I worked on my changes for NFS server, I verified implementation of netconfig related function in RPC part of libc and not closed netconfig handles results in memory leaks and one opened file descriptor for netconfig database. BTW there are several mistakes in that part of code, so I wrote correct implementation in kern/165710 (kern category was autoassigned). ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: mountd, rpc.lockd and rpc.statd patches for testing
On Thu, Apr 19, 2012 at 08:44:37PM -0400, Rick Macklem wrote: Andrey Simonenko wrote: 1. What is the sense to try to use the same port number for all supported netconfigs if specific port number is not given in a command line option? Well, there was a discussion of this on one of the mailing lists at the time. I started with a much simpler patch that didn't try and make all 4 udp/tcp, ip4/ip6 combinations use the same port#, but others felt that was important. (Something about tracking what port# were in use, but I can't quite recall. If you want to know the reasoning, look for the thread that would have been shortly before the commit.) That discussion was in stable@ mailing list under the subject statd/lockd startup failure started at February 2011. That discussion had two reasons to use one port for all netconfigs: 1) tracking network connections and 2) firewall configurations. If specific port number is not given in a command line, then this port number should be taken from rpcinfo output for example, so it should be taken manually or by some script. Anyway it will require some work to obtain a port number before using it in tcpdump or in firewall settings. I checked rpcinfo output for mountd on Solaris and NetBSD, on both systems mountd can use different ports for different netconfigs. 2. What is the sense of specifying specific IP addresses for mountd and similar RPC programs that do not have predefined port numbers? I'm not sure what you are asking here? (Are you referring to the -h command line option?) Yes, about the -h command line option. Such option works for nfsd, since it has predefined port number, but it will not work correctly for other RPC programs when specific port number is not given. Bigger number of specific addresses given in this option will increase probability that mountd will fail. There are several attempts to select one random port number for all netconfigs (and for all specified addresses), but these attempts do not guaranty that mountd will not fail. Several systems do not have -h like option for nfsd, mountd, etc. Looks like that when this option was proposed for mountd, rpc.statd and rpc.lockd it was not considered that using non wildcard address for RPC programs with not predefined port numbers does not fit with the RPC port mapper logic. (BTW rpc.lockd uses random port numbers for all netconfigs on 10-CURRENT and 9-STABLE). If the -h option (address) is really needed, then I would require to specify the -p option (port number) as well, at least one will know port number and can use it in firewall settings, but specifying unused port number is required for all combinations of netconfigs and addresses. Otherwise, successful start of mountd depends on number of -h options and network activity of other programs. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: mountd, rpc.lockd and rpc.statd patches for testing
On Mon, May 30, 2011 at 04:56:02PM -0400, Rick Macklem wrote: Hi, I have patches for the mountd, rpc.statd and rpc.lockd daemons that are meant to keep them from failing when a dynamically selected port# is not available for some combination of udp,tcp X ipv4,ipv6 If anyone would like to test these patches, they can be found at: http://people.freebsd.org/~rmacklem/mountd.patch statd.patch lockd.patch Although I think I got them correct, they are rather big and ugly. I have checked this update for mountd in 10-CURRENT and has two questions: 1. What is the sense to try to use the same port number for all supported netconfigs if specific port number is not given in a command line option? 2. What is the sense of specifying specific IP addresses for mountd and similar RPC programs that do not have predefined port numbers? -- One comment for netconfig related functions usage. Each setnetconfig() call allocates memory and depending on implementation can use other resources, so endnetconfig() should be called before reusing netconfig handle. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: -ffast-math in Ports and wrong generated code
On Wed, Apr 04, 2012 at 09:45:25AM -0500, Pedro Giffuni wrote: On 04/04/12 04:29, Andrey Simonenko wrote: On Tue, Apr 03, 2012 at 06:43:00AM -0700, Steve Kargl wrote: On Tue, Apr 03, 2012 at 02:21:11PM +0300, Andrey Simonenko wrote: I use one port from the Ports Collection, that works with FP. Having reinstalled it (its version was not changed) I noticed that it started to work incorrectly. After debugging and disassembling its code I found out that the -ffast-math option used for building was the result of wrongly generated code (I did not specify this option in /etc/make.conf). At least finite() function call was eliminated from the result Assembler code when -ffast-math option is used, tested on 9.0-STABLE and 10.0-CURRENT. Example test source code and generated code under 9.0-STABLE on amd64 by gcc from the base system: - #includemath.h #includestdio.h void check_finite(double x) { printf(%d\n, finite(x)); } - % gcc -Wall -O2 -S finite.c - check_finite: .LFB3: subq$8, %rsp .LCFI0: callfinite -- call to finite() movl$.LC0, %edi movl%eax, %esi addq$8, %rsp xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - % gcc -Wall -O2 -ffast-math -S finite.c - check_finite: .LFB3: xorl%esi, %esi -- fake result from finite() movl$.LC0, %edi xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - Can somebody comment this? Read the man page for gcc. With --fast-math, gcc assumes that the result of any FP operation is finite. So, the function call to finite() is eliminated as it is always true. Looks like that I was misunderstood. I did not ask why finite() was eliminated, I asked why fake result from finite() is wrong. Obviously that -ffast-math can optimize FP arithmetics and as a result some functions can be eliminated. The problem is not respecting IEEE specifications for FP, the problem is wrongly generated code when -ffast-math is used. Actually there is a bug in GCC used in the base system. There was made a change to builtins.c from gcc in revision 1.12 [1] and as a result gcc started to eliminate finite() function calls with -ffinite-math-only. ... After this change the corresponding Assembler code for my test file is: % gcc -Wall -O2 -ffast-math -S finite.c - check_finite: .LFB3: movl$1, %esi-- fake result from finite() movl$.LC0, %edi xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - What do you think? If there is no objections, I'll create PR. [1] http://www.freebsd.org/cgi/cvsweb.cgi/src/contrib/gcc/builtins.c.diff?r1=1.11;r2=1.12 ___ The SVN commit http://svnweb.freebsd.org/base?view=revisionrevision=228756 will point you to this: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28796 and we are keeping consistency with both upstream and Apple's gcc. Well, I've found exact commit to upstream gcc source tree that corrects the bug described above: http://gcc.gnu.org/viewcvs/trunk/gcc/builtins.c?r1=117751r2=117929 I think that nobody even tried to run my test program, so I'll post here results from my system (I did not post this test before just to make the post brief): % uname -omr FreeBSD 9.0-STABLE amd64 % cc -v Using built-in specs. Target: amd64-undermydesk-freebsd Configured with: FreeBSD/amd64 system compiler Thread model: posix gcc version 4.2.1 20070831 patched [FreeBSD] % cat finite.c #include math.h #include stdio.h void check_finite(double x) { printf( %d , finite(x)); } int main(void) { double x; for (x = -2; x 2; x += 0.5) { printf(%.1f, x); check_finite(x); } printf(\n); return (0); } % cc -Wall -O2 finite.c -lm % ./a.out -2.0 1 -1.5 1 -1.0 1 -0.5 1 0.0 1 0.5 1 1.0 1 1.5 1 % cc -Wall -O2 -ffinite-math-only finite.c -lm % ./a.out -2.0 0 -1.5 0 -1.0 0 -0.5 0 0.0 0 0.5 0 1.0 0 1.5 0 Should not both results be the same? ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: -ffast-math in Ports and wrong generated code
On Tue, Apr 03, 2012 at 06:43:00AM -0700, Steve Kargl wrote: On Tue, Apr 03, 2012 at 02:21:11PM +0300, Andrey Simonenko wrote: I use one port from the Ports Collection, that works with FP. Having reinstalled it (its version was not changed) I noticed that it started to work incorrectly. After debugging and disassembling its code I found out that the -ffast-math option used for building was the result of wrongly generated code (I did not specify this option in /etc/make.conf). At least finite() function call was eliminated from the result Assembler code when -ffast-math option is used, tested on 9.0-STABLE and 10.0-CURRENT. Example test source code and generated code under 9.0-STABLE on amd64 by gcc from the base system: - #include math.h #include stdio.h void check_finite(double x) { printf(%d\n, finite(x)); } - % gcc -Wall -O2 -S finite.c - check_finite: .LFB3: subq$8, %rsp .LCFI0: callfinite -- call to finite() movl$.LC0, %edi movl%eax, %esi addq$8, %rsp xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - % gcc -Wall -O2 -ffast-math -S finite.c - check_finite: .LFB3: xorl%esi, %esi -- fake result from finite() movl$.LC0, %edi xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - Can somebody comment this? Read the man page for gcc. With --fast-math, gcc assumes that the result of any FP operation is finite. So, the function call to finite() is eliminated as it is always true. Looks like that I was misunderstood. I did not ask why finite() was eliminated, I asked why fake result from finite() is wrong. Obviously that -ffast-math can optimize FP arithmetics and as a result some functions can be eliminated. The problem is not respecting IEEE specifications for FP, the problem is wrongly generated code when -ffast-math is used. Actually there is a bug in GCC used in the base system. There was made a change to builtins.c from gcc in revision 1.12 [1] and as a result gcc started to eliminate finite() function calls with -ffinite-math-only. The true result from finite() is non-zero value, but GCC generated always false value, so any program that uses finite() and has -ffinite-math-only works incorrectly if it was built by this version of gcc. Here is the correction for builtins.c: --- builtins.c.orig 2012-01-06 14:50:41.0 +0200 +++ builtins.c 2012-04-04 10:27:23.0 +0300 @@ -8738,7 +8738,7 @@ fold_builtin_classify (tree fndecl, tree case BUILT_IN_FINITE: if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))) !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg - return omit_one_operand (type, integer_zero_node, arg); + return omit_one_operand (type, integer_one_node, arg); if (TREE_CODE (arg) == REAL_CST) { After this change the corresponding Assembler code for my test file is: % gcc -Wall -O2 -ffast-math -S finite.c - check_finite: .LFB3: movl$1, %esi-- fake result from finite() movl$.LC0, %edi xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - What do you think? If there is no objections, I'll create PR. [1] http://www.freebsd.org/cgi/cvsweb.cgi/src/contrib/gcc/builtins.c.diff?r1=1.11;r2=1.12 ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
-ffast-math in Ports and wrong generated code
Hello, I use one port from the Ports Collection, that works with FP. Having reinstalled it (its version was not changed) I noticed that it started to work incorrectly. After debugging and disassembling its code I found out that the -ffast-math option used for building was the result of wrongly generated code (I did not specify this option in /etc/make.conf). At least finite() function call was eliminated from the result Assembler code when -ffast-math option is used, tested on 9.0-STABLE and 10.0-CURRENT. Example test source code and generated code under 9.0-STABLE on amd64 by gcc from the base system: - #include math.h #include stdio.h void check_finite(double x) { printf(%d\n, finite(x)); } - % gcc -Wall -O2 -S finite.c - check_finite: .LFB3: subq$8, %rsp .LCFI0: callfinite -- call to finite() movl$.LC0, %edi movl%eax, %esi addq$8, %rsp xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - % gcc -Wall -O2 -ffast-math -S finite.c - check_finite: .LFB3: xorl%esi, %esi -- fake result from finite() movl$.LC0, %edi xorl%eax, %eax jmp printf .LFE3: .size check_finite, .-check_finite - Can somebody comment this? ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org
Re: [head tinderbox] failure on ia64/ia64
On Mon, Jan 31, 2011 at 04:56:06PM -0800, Marcel Moolenaar wrote: Take the statement at line 116 for example: *((int *)CMSG_DATA(cmsg)) = fd; We're effectively casting from a (char *) to a (int *) and then doing a 32-bit access (write). The easy fix (casting through (void *) is not possible, because you cannot guarantee that the address is properly aligned. cmsg points to memory set aside by the following local variable: unsigned char ctrl[CMSG_SPACE(sizeof(fd))]; There's no guarantee that the compiler will align the character array at a 32-bit boundary (though in practice it seems to be). I have seen this kind of construct fail on ARM and PowerPC for example. Why not to use such declaration: union { struct cmsghdr cm; char ctrl[CMSG_SPACE(sizeof(fd))]; } control_un; At least this is necessary to satisfy that CMSG_FIRSTHDR() will give address of correctly aligned struct cmsghdr{}. ___ freebsd-current@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org