git: ffa6993a1513 - main - net/netatalk3: Add a slew of upstream patches.

From: Joe Marcus Clarke <marcus_at_FreeBSD.org>
Date: Tue, 27 Sep 2022 17:39:10 UTC
The branch main has been updated by marcus:

URL: https://cgit.FreeBSD.org/ports/commit/?id=ffa6993a15138fb02145d8e523d2f71adc2930a5

commit ffa6993a15138fb02145d8e523d2f71adc2930a5
Author:     Joe Marcus Clarke <marcus@FreeBSD.org>
AuthorDate: 2022-09-27 17:37:31 +0000
Commit:     Joe Marcus Clarke <marcus@FreeBSD.org>
CommitDate: 2022-09-27 17:37:31 +0000

    net/netatalk3: Add a slew of upstream patches.
    
    These are primarily focused on clearing out the remaining CVE fix
    fallout.  They handle the cases where ad_entries can be NULL, don't
    remove metadata, and don't allow adouble for symlinks.
    
    PR:             263123
---
 net/netatalk3/Makefile                             |   2 +-
 net/netatalk3/files/patch-configure                |   6 +-
 net/netatalk3/files/patch-etc_afpd_directory.c     |  53 +++++
 net/netatalk3/files/patch-etc_afpd_file.c          | 127 +++++++++++
 net/netatalk3/files/patch-etc_afpd_volume.c        |  37 ++--
 .../files/patch-etc_cnid__dbd_cmd__dbd__scanvol.c  |  25 +++
 .../files/patch-libatalk_adouble_ad__attr.c        | 234 +++++++++++++++++++++
 .../files/patch-libatalk_adouble_ad__conv.c        |  27 +++
 .../files/patch-libatalk_adouble_ad__date.c        |  48 +++++
 .../files/patch-libatalk_adouble_ad__flush.c       |  68 ++++++
 .../files/patch-libatalk_adouble_ad__open.c        | 167 ++++++++-------
 11 files changed, 696 insertions(+), 98 deletions(-)

diff --git a/net/netatalk3/Makefile b/net/netatalk3/Makefile
index 87e0f5fd840f..71d081b6c62c 100644
--- a/net/netatalk3/Makefile
+++ b/net/netatalk3/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	netatalk
 PORTVERSION=	3.1.13
-PORTREVISION=	2
+PORTREVISION=	3
 PORTEPOCH=	1
 CATEGORIES=	net
 MASTER_SITES=	SF
diff --git a/net/netatalk3/files/patch-configure b/net/netatalk3/files/patch-configure
index 5b24b6253404..907721778bc7 100644
--- a/net/netatalk3/files/patch-configure
+++ b/net/netatalk3/files/patch-configure
@@ -1,11 +1,11 @@
---- configure.orig	2016-09-12 09:54:34 UTC
+--- configure.orig	2022-03-22 04:51:09 UTC
 +++ configure
-@@ -17360,7 +17360,7 @@ if test "x$bdb_required" = "xyes"; then
+@@ -17368,7 +17368,7 @@ if test "x$bdb_required" = "xyes"; then
      trybdbdir=""
      dobdbsearch=yes
      bdb_search_dirs="/usr/local /usr"
 -    search_subdirs="/ /db6.1 /db6 /db5 /db5.3 /db5.2 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
-+    search_subdirs="/%%DB_NAME%% / /db6.1 /db6 /db5 /db5.3 /db5.2 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
++    search_subdirs="/db5 / /db6.1 /db6 /db5 /db5.3 /db5.2 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
  
      bdbfound=no
      savedcflags="$CFLAGS"
diff --git a/net/netatalk3/files/patch-etc_afpd_directory.c b/net/netatalk3/files/patch-etc_afpd_directory.c
new file mode 100644
index 000000000000..5383bc1d271b
--- /dev/null
+++ b/net/netatalk3/files/patch-etc_afpd_directory.c
@@ -0,0 +1,53 @@
+--- etc/afpd/directory.c.orig	2022-02-28 13:32:06 UTC
++++ etc/afpd/directory.c
+@@ -1426,6 +1426,7 @@ int getdirparams(const AFPObj *obj,
+     struct maccess  ma;
+     struct adouble  ad;
+     char        *data, *l_nameoff = NULL, *utf_nameoff = NULL;
++    char        *ade = NULL;
+     int         bit = 0, isad = 0;
+     uint32_t           aint;
+     uint16_t       ashort;
+@@ -1520,7 +1521,10 @@ int getdirparams(const AFPObj *obj,
+ 
+         case DIRPBIT_FINFO :
+             if ( isad ) {
+-                memcpy( data, ad_entry( &ad, ADEID_FINDERI ), 32 );
++                ade = ad_entry(&ad, ADEID_FINDERI);
++                AFP_ASSERT(ade != NULL);
++
++                memcpy( data, ade, 32 );
+             } else { /* no appledouble */
+                 memset( data, 0, 32 );
+                 /* dot files are by default visible */
+@@ -1744,6 +1748,7 @@ int setdirparams(struct vol *vol, struct path *path, u
+     struct timeval      tv;
+ 
+     char                *upath;
++    char                *ade = NULL;
+     struct dir          *dir;
+     int         bit, isad = 0;
+     int                 cdate, bdate;
+@@ -1905,6 +1910,8 @@ int setdirparams(struct vol *vol, struct path *path, u
+                 fflags &= htons(~FINDERINFO_ISHARED);
+                 memcpy(finder_buf + FINDERINFO_FRFLAGOFF, &fflags, sizeof(uint16_t));
+                 /* #2802236 end */
++                ade = ad_entry(&ad, ADEID_FINDERI);
++                AFP_ASSERT(ade != NULL);
+ 
+                 if (  dir->d_did == DIRDID_ROOT ) {
+                     /*
+@@ -1915,10 +1922,10 @@ int setdirparams(struct vol *vol, struct path *path, u
+                      * behavior one sees when mounting above another mount
+                      * point.
+                      */
+-                    memcpy( ad_entry( &ad, ADEID_FINDERI ), finder_buf, 10 );
+-                    memcpy( ad_entry( &ad, ADEID_FINDERI ) + 14, finder_buf + 14, 18 );
++                    memcpy( ade, finder_buf, 10 );
++                    memcpy( ade + 14, finder_buf + 14, 18 );
+                 } else {
+-                    memcpy( ad_entry( &ad, ADEID_FINDERI ), finder_buf, 32 );
++                    memcpy( ade, finder_buf, 32 );
+                 }
+             }
+             break;
diff --git a/net/netatalk3/files/patch-etc_afpd_file.c b/net/netatalk3/files/patch-etc_afpd_file.c
new file mode 100644
index 000000000000..db49f4c60a27
--- /dev/null
+++ b/net/netatalk3/files/patch-etc_afpd_file.c
@@ -0,0 +1,127 @@
+--- etc/afpd/file.c.orig	2022-02-28 13:32:06 UTC
++++ etc/afpd/file.c
+@@ -296,6 +296,7 @@ int getmetadata(const AFPObj *obj,
+ {
+     char		*data, *l_nameoff = NULL, *upath;
+     char                *utf_nameoff = NULL;
++    char		*ade = NULL;
+     int			bit = 0;
+     uint32_t		aint;
+     cnid_t              id = 0;
+@@ -497,8 +498,11 @@ int getmetadata(const AFPObj *obj,
+             }
+             else {
+                 if ( adp ) {
+-                    memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 );
++                    ade = ad_entry(adp, ADEID_FINDERI);
++                    AFP_ASSERT(ade != NULL);
+ 
++                    memcpy(fdType, ade, 4);
++
+                     if ( memcmp( fdType, "TEXT", 4 ) == 0 ) {
+                         achar = '\x04';
+                         ashort = 0x0000;
+@@ -576,8 +580,19 @@ int getmetadata(const AFPObj *obj,
+                10.3 clients freak out. */
+ 
+     	    aint = st->st_mode;
+- 	    if (adp) {
+-	        memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 );
++            /*
++             * ad_open() does not initialize adouble header
++             * for symlinks. Hence this should be skipped to
++             * avoid AFP_ASSERT here. Decision was made to
++             * not alter ad_open() behavior so that
++             * improper ops on symlink adoubles will be
++             * more visible (assert).
++             */
++            if (adp && (ad_meta_fileno(adp) != AD_SYMLINK)) {
++                ade = ad_entry(adp, ADEID_FINDERI);
++                AFP_ASSERT(ade != NULL);
++
++	        memcpy(fdType, ade, 4);
+                 if ( memcmp( fdType, "slnk", 4 ) == 0 ) {
+ 	 	    aint |= S_IFLNK;
+             	}
+@@ -839,6 +854,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
+     struct extmap	*em;
+     int			bit, isad = 1, err = AFP_OK;
+     char                *upath;
++    char		*ade = NULL;
+     u_char              achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
+     uint16_t		ashort, bshort, oshort;
+     uint32_t		aint;
+@@ -989,7 +1005,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
+     /* second try with adouble open 
+     */
+     if (ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) < 0) {
+-        LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error");
++        LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error: %s", strerror(errno));
+         /*
+          * For some things, we don't need an adouble header:
+          * - change of modification date
+@@ -1021,6 +1037,9 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
+ 
+         switch(  bit ) {
+         case FILPBIT_ATTR :
++            if (isad == 0) {
++                break;
++            }
+             ad_getattr(adp, &bshort);
+             oshort = bshort;
+             if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
+@@ -1034,15 +1053,26 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
+             ad_setattr(adp, bshort);
+             break;
+         case FILPBIT_CDATE :
++            if (isad == 0) {
++                break;
++            }
+             ad_setdate(adp, AD_DATE_CREATE, cdate);
+             break;
+         case FILPBIT_MDATE :
+             break;
+         case FILPBIT_BDATE :
++            if (isad == 0) {
++                break;
++            }
+             ad_setdate(adp, AD_DATE_BACKUP, bdate);
+             break;
+         case FILPBIT_FINFO :
+-            if (default_type( ad_entry( adp, ADEID_FINDERI ))
++            if (isad == 0) {
++                break;
++            }
++            ade = ad_entry(adp, ADEID_FINDERI);
++            AFP_ASSERT(ade != NULL);
++            if (default_type(ade)
+                     && ( 
+                      ((em = getextmap( path->m_name )) &&
+                       !memcmp(finder_buf, em->em_type, sizeof( em->em_type )) &&
+@@ -1053,7 +1083,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
+             )) {
+                 memcpy(finder_buf, ufinderi, 8 );
+             }
+-            memcpy(ad_entry( adp, ADEID_FINDERI ), finder_buf, 32 );
++            memcpy(ade, finder_buf, 32 );
+             break;
+         case FILPBIT_UNIXPR :
+             if (upriv_bit) {
+@@ -1061,9 +1091,15 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
+             }
+             break;
+         case FILPBIT_PDINFO :
++            if (isad == 0) {
++                break;
++            }
++            ade = ad_entry(adp, ADEID_FINDERI);
++            AFP_ASSERT(ade != NULL);
++
+             if (obj->afp_version < 30) { /* else it's UTF8 name */
+-                memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
+-                memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
++                memcpy(ade, fdType, 4 );
++                memcpy(ade + 4, "pdos", 4 );
+                 break;
+             }
+             /* fallthrough */
diff --git a/net/netatalk3/files/patch-etc_afpd_volume.c b/net/netatalk3/files/patch-etc_afpd_volume.c
index cc13c172a9bd..f7edbf34488c 100644
--- a/net/netatalk3/files/patch-etc_afpd_volume.c
+++ b/net/netatalk3/files/patch-etc_afpd_volume.c
@@ -1,20 +1,23 @@
---- etc/afpd/volume.c.orig	2020-11-17 04:41:20 UTC
+--- etc/afpd/volume.c.orig	2022-03-22 04:50:23 UTC
 +++ etc/afpd/volume.c
-@@ -183,6 +183,7 @@ static int get_tm_used(struct vol * restrict vol)
-             
-             if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) {
-                 bdestroy(infoplist);
-+                infoplist = NULL;
-                 continue;
-             }
+@@ -305,6 +305,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bi
+     VolSpace            xbfree, xbtotal; /* extended bytes */
+     char        *data, *nameoff = NULL;
+     char                *slash;
++    char        *ade = NULL;
  
-@@ -190,7 +191,9 @@ static int get_tm_used(struct vol * restrict vol)
- 
-             if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) {
-                 bdestroy(infoplist);
-+                infoplist = NULL;
-                 bdestroy(bandsdir);
-+                bandsdir = NULL;
-                 continue;
-             }
+     LOG(log_debug, logtype_afpd, "getvolparams: Volume '%s'", vol->v_localname);
  
+@@ -328,8 +329,10 @@ static int getvolparams(const AFPObj *obj, uint16_t bi
+             slash = vol->v_path;
+         if (ad_getentryoff(&ad, ADEID_NAME)) {
+             ad_setentrylen( &ad, ADEID_NAME, strlen( slash ));
+-            memcpy(ad_entry( &ad, ADEID_NAME ), slash,
+-                   ad_getentrylen( &ad, ADEID_NAME ));
++            ade = ad_entry(&ad, ADEID_NAME);
++            AFP_ASSERT(ade != NULL);
++
++            memcpy(ade, slash, ad_getentrylen( &ad, ADEID_NAME ));
+         }
+         vol_setdate(vol->v_vid, &ad, st->st_mtime);
+         ad_flush(&ad);
diff --git a/net/netatalk3/files/patch-etc_cnid__dbd_cmd__dbd__scanvol.c b/net/netatalk3/files/patch-etc_cnid__dbd_cmd__dbd__scanvol.c
new file mode 100644
index 000000000000..c1fba532eaac
--- /dev/null
+++ b/net/netatalk3/files/patch-etc_cnid__dbd_cmd__dbd__scanvol.c
@@ -0,0 +1,25 @@
+--- etc/cnid_dbd/cmd_dbd_scanvol.c.orig	2022-02-28 13:32:06 UTC
++++ etc/cnid_dbd/cmd_dbd_scanvol.c
+@@ -560,6 +560,7 @@ static int read_addir(void)
+ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok)
+ {
+     int adflags = ADFLAGS_HF;
++    int err;
+     cnid_t db_cnid, ad_cnid;
+     struct adouble ad;
+ 
+@@ -602,7 +603,13 @@ static cnid_t check_cnid(const char *name, cnid_t did,
+                     cwdbuf, name, strerror(errno));
+             return CNID_INVALID;
+         }
+-        ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
++        err = ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
++        if (err == -1) {
++            dbd_log(LOGSTD, "Error setting new CNID, malformed adouble: '%s/%s'",
++                    cwdbuf, name);
++            ad_close(&ad, ADFLAGS_HF);
++            return CNID_INVALID;
++        }
+         ad_flush(&ad);
+         ad_close(&ad, ADFLAGS_HF);
+     }
diff --git a/net/netatalk3/files/patch-libatalk_adouble_ad__attr.c b/net/netatalk3/files/patch-libatalk_adouble_ad__attr.c
new file mode 100644
index 000000000000..cafffaed5987
--- /dev/null
+++ b/net/netatalk3/files/patch-libatalk_adouble_ad__attr.c
@@ -0,0 +1,234 @@
+--- libatalk/adouble/ad_attr.c.orig	2022-02-28 13:32:06 UTC
++++ libatalk/adouble/ad_attr.c
+@@ -2,8 +2,10 @@
+ #include "config.h"
+ #endif /* HAVE_CONFIG_H */
+ 
++#include <stdlib.h>
+ #include <string.h>
+ #include <arpa/inet.h>
++#include <atalk/util.h>
+ #include <atalk/adouble.h>
+ #include <atalk/logger.h>
+ 
+@@ -22,10 +24,17 @@ int ad_getattr(const struct adouble *ad, uint16_t *att
+     *attr = 0;
+ 
+     if (ad_getentryoff(ad, ADEID_AFPFILEI)) {
+-        memcpy(attr, ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, 2);
++        char *adp = NULL;
+ 
++        adp = ad_entry(ad, ADEID_AFPFILEI);
++        AFP_ASSERT(adp != NULL);
++        memcpy(attr, adp + AFPFILEIOFF_ATTR, 2);
++
+         /* Now get opaque flags from FinderInfo */
+-        memcpy(&fflags, ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, 2);
++        adp = ad_entry(ad, ADEID_FINDERI);
++        AFP_ASSERT(adp != NULL);
++        memcpy(&fflags, adp + FINDERINFO_FRFLAGOFF, 2);
++
+         if (fflags & htons(FINDERINFO_INVISIBLE))
+             *attr |= htons(ATTRBIT_INVISIBLE);
+         else
+@@ -61,10 +70,15 @@ int ad_setattr(const struct adouble *ad, const uint16_
+         attr &= ~(ATTRBIT_MULTIUSER | ATTRBIT_NOWRITE | ATTRBIT_NOCOPY);
+ 
+     if (ad_getentryoff(ad, ADEID_AFPFILEI) && ad_getentryoff(ad, ADEID_FINDERI)) {
+-        memcpy(ad_entry(ad, ADEID_AFPFILEI) + AFPFILEIOFF_ATTR, &attr, sizeof(attr));
++        char *adp = NULL;
++
++        adp = ad_entry(ad, ADEID_FINDERI);
++        AFP_ASSERT(adp != NULL);
++
++        memcpy(adp + AFPFILEIOFF_ATTR, &attr, sizeof(attr));
+             
+         /* Now set opaque flags in FinderInfo too */
+-        memcpy(&fflags, ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, 2);
++        memcpy(&fflags, adp + FINDERINFO_FRFLAGOFF, 2);
+         if (attr & htons(ATTRBIT_INVISIBLE))
+             fflags |= htons(FINDERINFO_INVISIBLE);
+         else
+@@ -77,7 +91,7 @@ int ad_setattr(const struct adouble *ad, const uint16_
+         } else
+             fflags &= htons(~FINDERINFO_ISHARED);
+ 
+-        memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &fflags, 2);
++        memcpy(adp + FINDERINFO_FRFLAGOFF, &fflags, 2);
+     }
+ 
+     return 0;
+@@ -86,54 +100,114 @@ int ad_setattr(const struct adouble *ad, const uint16_
+ /* --------------
+  * save file/folder ID in AppleDoubleV2 netatalk private parameters
+  * return 1 if resource fork has been modified
++ * return -1 on error.
+  */
+ int ad_setid (struct adouble *adp, const dev_t dev, const ino_t ino , const uint32_t id, const cnid_t did, const void *stamp)
+ {
+     uint32_t tmp;
++    char *ade = NULL;
+ 
+     ad_setentrylen( adp, ADEID_PRIVID, sizeof(id));
+     tmp = id;
+     if (adp->ad_vers == AD_VERSION_EA)
+         tmp = htonl(tmp);
+-    memcpy(ad_entry( adp, ADEID_PRIVID ), &tmp, sizeof(tmp));
+ 
++    ade = ad_entry(adp, ADEID_PRIVID);
++    if (ade == NULL) {
++        LOG(log_warning, logtype_ad, "ad_setid: failed to set ADEID_PRIVID\n");
++        return -1;
++    }
++    memcpy(ade, &tmp, sizeof(tmp));
++
+     ad_setentrylen( adp, ADEID_PRIVDEV, sizeof(dev_t));
++    ade = ad_entry(adp, ADEID_PRIVDEV);
++    if (ade == NULL) {
++        LOG(log_warning, logtype_ad, "ad_setid: failed to set ADEID_PRIVDEV\n");
++        return -1;
++    }
++
+     if ((adp->ad_options & ADVOL_NODEV)) {
+-        memset(ad_entry( adp, ADEID_PRIVDEV ), 0, sizeof(dev_t));
++        memset(ade, 0, sizeof(dev_t));
+     } else {
+-        memcpy(ad_entry( adp, ADEID_PRIVDEV ), &dev, sizeof(dev_t));
++        memcpy(ade, &dev, sizeof(dev_t));
+     }
+ 
+     ad_setentrylen( adp, ADEID_PRIVINO, sizeof(ino_t));
+-    memcpy(ad_entry( adp, ADEID_PRIVINO ), &ino, sizeof(ino_t));
+ 
+-    ad_setentrylen( adp, ADEID_DID, sizeof(did));
+-    memcpy(ad_entry( adp, ADEID_DID ), &did, sizeof(did));
++    ade = ad_entry(adp, ADEID_PRIVINO);
++    if (ade == NULL) {
++        LOG(log_warning, logtype_ad, "ad_setid: failed to set ADEID_PRIVINO\n");
++        return -1;
++    }
++    memcpy(ade, &ino, sizeof(ino_t));
+ 
++    if (adp->ad_vers != AD_VERSION_EA) {
++        ad_setentrylen( adp, ADEID_DID, sizeof(did));
++
++        ade = ad_entry(adp, ADEID_DID);
++        if (ade == NULL) {
++            LOG(log_warning, logtype_ad, "ad_setid: failed to set ADEID_DID\n");
++            return -1;
++        }
++        memcpy(ade, &did, sizeof(did));
++    }
++
+     ad_setentrylen( adp, ADEID_PRIVSYN, ADEDLEN_PRIVSYN);
+-    memcpy(ad_entry( adp, ADEID_PRIVSYN ), stamp, ADEDLEN_PRIVSYN);
++    ade = ad_entry(adp, ADEID_PRIVSYN);
++    if (ade == NULL) {
++        LOG(log_warning, logtype_ad, "ad_setid: failed to set ADEID_PRIVSYN\n");
++        return -1;
++    }
++    memcpy(ade, stamp, ADEDLEN_PRIVSYN);
+ 
+     return 1;
+ }
+ 
+-/* ----------------------------- */
++/*
++ * Retrieve stored file / folder. Callers should treat a return of CNID_INVALID (0) as an invalid value.
++ */
+ uint32_t ad_getid (struct adouble *adp, const dev_t st_dev, const ino_t st_ino , const cnid_t did, const void *stamp _U_)
+ {
+     uint32_t aint = 0;
+     dev_t  dev;
+     ino_t  ino;
+-    cnid_t a_did;
++    cnid_t a_did = 0;
+ 
+     if (adp) {
+         if (sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)) {
+-            memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t));
+-            memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t));
+-            memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t));
++            char *ade = NULL;
++            ade = ad_entry(adp, ADEID_PRIVDEV);
++            if (ade == NULL) {
++                LOG(log_warning, logtype_ad, "ad_getid: failed to retrieve ADEID_PRIVDEV\n");
++                return CNID_INVALID;
++            }
++            memcpy(&dev, ade, sizeof(dev_t));
++            ade = ad_entry(adp, ADEID_PRIVINO);
++            if (ade == NULL) {
++                LOG(log_warning, logtype_ad, "ad_getid: failed to retrieve ADEID_PRIVINO\n");
++                return CNID_INVALID;
++            }
++            memcpy(&ino, ade, sizeof(ino_t));
+ 
++            if (adp->ad_vers != AD_VERSION_EA) {
++                /* ADEID_DID is not stored for AD_VERSION_EA */
++                ade = ad_entry(adp, ADEID_DID);
++                if (ade == NULL) {
++                    LOG(log_warning, logtype_ad, "ad_getid: failed to retrieve ADEID_DID\n");
++                    return CNID_INVALID;
++                }
++                memcpy(&a_did, ade, sizeof(cnid_t));
++            }
++
+             if (((adp->ad_options & ADVOL_NODEV) || (dev == st_dev))
+                 && ino == st_ino
+-                && (!did || a_did == did) ) {
+-                memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
++                && (!did || a_did == 0 || a_did == did) ) {
++                ade = ad_entry(adp, ADEID_PRIVID);
++                if (ade == NULL) {
++                    LOG(log_warning, logtype_ad, "ad_getid: failed to retrieve ADEID_PRIVID\n");
++                    return CNID_INVALID;
++                }
++                memcpy(&aint, ade, sizeof(aint));
+                 if (adp->ad_vers == AD_VERSION2)
+                     return aint;
+                 else
+@@ -141,7 +215,7 @@ uint32_t ad_getid (struct adouble *adp, const dev_t st
+             }
+         }
+     }
+-    return 0;
++    return CNID_INVALID;
+ }
+ 
+ /* ----------------------------- */
+@@ -150,13 +224,18 @@ uint32_t ad_forcegetid (struct adouble *adp)
+     uint32_t aint = 0;
+ 
+     if (adp) {
+-        memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
++        char *ade = NULL;
++        ade = ad_entry(adp, ADEID_PRIVID);
++        if (ade == NULL) {
++            return CNID_INVALID;
++        }
++        memcpy(&aint, ade, sizeof(aint));
+         if (adp->ad_vers == AD_VERSION2)
+             return aint;
+         else
+             return ntohl(aint);
+     }
+-    return 0;
++    return CNID_INVALID;
+ }
+ 
+ /* -----------------
+@@ -168,8 +247,13 @@ int ad_setname(struct adouble *ad, const char *path)
+     if ((len = strlen(path)) > ADEDLEN_NAME)
+         len = ADEDLEN_NAME;
+     if (path && ad_getentryoff(ad, ADEID_NAME)) {
++        char *ade = NULL;
+         ad_setentrylen( ad, ADEID_NAME, len);
+-        memcpy(ad_entry( ad, ADEID_NAME ), path, len);
++        ade = ad_entry(ad, ADEID_NAME);
++        if (ade == NULL) {
++            return -1;
++        }
++        memcpy(ade, path, len);
+         return 1;
+     }
+     return 0;
diff --git a/net/netatalk3/files/patch-libatalk_adouble_ad__conv.c b/net/netatalk3/files/patch-libatalk_adouble_ad__conv.c
new file mode 100644
index 000000000000..e2369bc9df20
--- /dev/null
+++ b/net/netatalk3/files/patch-libatalk_adouble_ad__conv.c
@@ -0,0 +1,27 @@
+--- libatalk/adouble/ad_conv.c.orig	2022-02-28 13:32:06 UTC
++++ libatalk/adouble/ad_conv.c
+@@ -93,6 +93,7 @@ static int ad_conv_v22ea_hf(const char *path, const st
+         goto copy;
+     if (ad_getentryoff(&adv2, ADEID_FINDERI)
+         && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
++        && (ad_entry(&adv2, ADEID_FINDERI) != NULL)
+         && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
+         goto copy;
+     if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
+@@ -101,7 +102,7 @@ static int ad_conv_v22ea_hf(const char *path, const st
+         if ((ctime != mtime) || (mtime != sp->st_mtime))
+             goto copy;
+     }
+-    if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
++    if (ad_getentryoff(&adv2, ADEID_AFPFILEI) && (ad_entry(&adv2, ADEID_AFPFILEI) != NULL)) {
+         if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
+             goto copy;
+     }
+@@ -115,6 +116,7 @@ copy:
+     EC_ZERO_LOGSTR( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE),
+                     "ad_conv_v22ea_hf(\"%s\"): error creating metadata EA: %s",
+                     fullpathname(path), strerror(errno));
++    AFP_ASSERT(ad_refresh(path, &adea) == 0);
+     EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
+     ad_flush(&adea);
+ 
diff --git a/net/netatalk3/files/patch-libatalk_adouble_ad__date.c b/net/netatalk3/files/patch-libatalk_adouble_ad__date.c
new file mode 100644
index 000000000000..2b0d129cd7e8
--- /dev/null
+++ b/net/netatalk3/files/patch-libatalk_adouble_ad__date.c
@@ -0,0 +1,48 @@
+--- libatalk/adouble/ad_date.c.orig	2022-02-28 13:32:06 UTC
++++ libatalk/adouble/ad_date.c
+@@ -10,6 +10,7 @@ int ad_setdate(struct adouble *ad,
+                unsigned int dateoff, uint32_t date)
+ {
+     int xlate = (dateoff & AD_DATE_UNIX);
++    char *ade = NULL;
+ 
+     dateoff &= AD_DATE_MASK;
+     if (xlate)
+@@ -20,8 +21,13 @@ int ad_setdate(struct adouble *ad,
+ 
+     if (dateoff > AD_DATE_ACCESS)
+         return -1;
+-    memcpy(ad_entry(ad, ADEID_FILEDATESI) + dateoff, &date, sizeof(date));
+ 
++    ade = ad_entry(ad, ADEID_FILEDATESI);
++    if (ade == NULL) {
++        return -1;
++    }
++    memcpy(ade + dateoff, &date, sizeof(date));
++
+     return 0;
+ }
+ 
+@@ -29,6 +35,7 @@ int ad_getdate(const struct adouble *ad,
+                unsigned int dateoff, uint32_t *date)
+ {
+     int xlate = (dateoff & AD_DATE_UNIX);
++    char *ade = NULL;
+ 
+     dateoff &= AD_DATE_MASK;
+     if (!ad_getentryoff(ad, ADEID_FILEDATESI))
+@@ -36,7 +43,13 @@ int ad_getdate(const struct adouble *ad,
+ 
+     if (dateoff > AD_DATE_ACCESS)
+         return -1;
+-    memcpy(date, ad_entry(ad, ADEID_FILEDATESI) + dateoff, sizeof(uint32_t));
++
++
++    ade = ad_entry(ad, ADEID_FILEDATESI);
++    if (ade == NULL) {
++        return -1;
++    }
++    memcpy(date, ade + dateoff, sizeof(uint32_t));
+ 
+     if (xlate)
+         *date = AD_DATE_TO_UNIX(*date);
diff --git a/net/netatalk3/files/patch-libatalk_adouble_ad__flush.c b/net/netatalk3/files/patch-libatalk_adouble_ad__flush.c
new file mode 100644
index 000000000000..032c0b3d6656
--- /dev/null
+++ b/net/netatalk3/files/patch-libatalk_adouble_ad__flush.c
@@ -0,0 +1,68 @@
+--- libatalk/adouble/ad_flush.c.orig	2022-03-22 04:50:23 UTC
++++ libatalk/adouble/ad_flush.c
+@@ -151,6 +151,7 @@ int ad_rebuild_adouble_header_osx(struct adouble *ad, 
+     uint32_t       temp;
+     uint16_t       nent;
+     char           *buf;
++    char           *ade = NULL;
+ 
+     LOG(log_debug, logtype_ad, "ad_rebuild_adouble_header_osx");
+ 
+@@ -184,8 +185,11 @@ int ad_rebuild_adouble_header_osx(struct adouble *ad, 
+     memcpy(buf, &temp, sizeof( temp ));
+     buf += sizeof( temp );
+ 
+-    memcpy(adbuf + ADEDOFF_FINDERI_OSX, ad_entry(ad, ADEID_FINDERI), ADEDLEN_FINDERI);
++    ade = ad_entry(ad, ADEID_FINDERI);
++    AFP_ASSERT(ade != NULL);
+ 
++    memcpy(adbuf + ADEDOFF_FINDERI_OSX, ade, ADEDLEN_FINDERI);
++
+     /* rfork */
+     temp = htonl( EID_DISK(ADEID_RFORK) );
+     memcpy(buf, &temp, sizeof( temp ));
+@@ -211,8 +215,12 @@ int ad_copy_header(struct adouble *add, struct adouble
+ {
+     uint32_t       eid;
+     uint32_t       len;
++    char *src = NULL;
++    char *dst = NULL;
+ 
+     for ( eid = 0; eid < ADEID_MAX; eid++ ) {
++        src = dst = NULL;
++
+         if ( ads->ad_eid[ eid ].ade_off == 0 || add->ad_eid[ eid ].ade_off == 0 )
+             continue;
+ 
+@@ -226,17 +234,28 @@ int ad_copy_header(struct adouble *add, struct adouble
+             continue;
+         default:
+             ad_setentrylen( add, eid, len );
+-            memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
++            dst = ad_entry(add, eid);
++            AFP_ASSERT(dst != NULL);
++
++            src = ad_entry(ads, eid);
++            AFP_ASSERT(src != NULL);
++
++            memcpy( dst, src, len );
+         }
+     }
+     add->ad_rlen = ads->ad_rlen;
+ 
+     if (((ads->ad_vers == AD_VERSION2) && (add->ad_vers == AD_VERSION_EA))
+         || ((ads->ad_vers == AD_VERSION_EA) && (add->ad_vers == AD_VERSION2))) {
++        src = dst = NULL;
+         cnid_t id;
+-        memcpy(&id, ad_entry(add, ADEID_PRIVID), sizeof(cnid_t));
++
++        dst = ad_entry(add, ADEID_PRIVID);
++        AFP_ASSERT(dst != NULL);
++
++        memcpy(&id, dst, sizeof(cnid_t));
+         id = htonl(id);
+-        memcpy(ad_entry(add, ADEID_PRIVID), &id, sizeof(cnid_t));
++        memcpy(dst, &id, sizeof(cnid_t));
+     }
+     return 0;
+ }
diff --git a/net/netatalk3/files/patch-libatalk_adouble_ad__open.c b/net/netatalk3/files/patch-libatalk_adouble_ad__open.c
index 9a704469a6de..a5a279834158 100644
--- a/net/netatalk3/files/patch-libatalk_adouble_ad__open.c
+++ b/net/netatalk3/files/patch-libatalk_adouble_ad__open.c
@@ -1,84 +1,97 @@
 --- libatalk/adouble/ad_open.c.orig	2022-03-22 04:44:25 UTC
 +++ libatalk/adouble/ad_open.c
-@@ -1574,6 +1574,8 @@ static bool ad_entry_check_size(uint32_t eid,
-     uint32_t required_len;
+@@ -140,17 +140,17 @@ static struct adouble_fops ad_adouble_ea = {
  
- 	if (eid >= ADEID_MAX) {
-+		LOG(log_error, logtype_ad, "ad_entry_check_size %d is greater than %d",
-+        	    eid, ADEID_MAX);
- 		return false;
- 	}
- 	if (got_len == 0) {
-@@ -1585,6 +1587,7 @@ static bool ad_entry_check_size(uint32_t eid,
- 		 * Shouldn't happen: implicitly initialized to zero because
- 		 * explicit initializer missing.
- 		 */
-+		LOG(log_error, logtype_ad, "ad_entry_check_size explicit initializer missing");
- 		return false;
- 	}
- 	if (ad_checks[eid].expected_len == -1) {
-@@ -1594,6 +1597,8 @@ static bool ad_entry_check_size(uint32_t eid,
- 	if (ad_checks[eid].fixed_size) {
- 		if (ad_checks[eid].expected_len != got_len) {
- 			/* Wrong size fo fixed size entry. */
-+			LOG(log_error, logtype_ad, "ad_entry_check_size wrong size to fixed size entry (%d != %d)",
-+        	    	    ad_checks[eid].expected_len, got_len);
- 			return false;
- 		}
-         required_len = got_len;
-@@ -1604,12 +1609,16 @@ static bool ad_entry_check_size(uint32_t eid,
- 				 * Too small for variable sized entry with
- 				 * minimum size.
- 				 */
-+				LOG(log_error, logtype_ad, "ad_entry_check_size too small for variable sized entry (%d < %d)",
-+        	    	    	    got_len, ad_checks[eid].expected_len);
- 				return false;
- 			}
-         required_len = got_len;
- 		} else {
- 			if (got_len > ad_checks[eid].expected_len) {
- 				/* Too big for variable sized entry. */
-+				LOG(log_error, logtype_ad, "ad_entry_check_size too big for variable sized entry (%d > %d)",
-+                                    got_len, ad_checks[eid].expected_len);
- 				return false;
- 			}
-             /*
-@@ -1621,10 +1630,14 @@ static bool ad_entry_check_size(uint32_t eid,
- 	}
- 	if (off + required_len < off) {
- 		/* wrap around */
-+		LOG(log_error, logtype_ad, "ad_entry_check_size wrap around (%d + %d < %d)",
-+                    off, required_len, off);
- 		return false;
- 	}
- 	if (off + required_len > bufsize) {
- 		/* overflow */
-+		LOG(log_error, logtype_ad, "ad_entry_check_size overflow (%d + %d > %d)",
-+                    off, required_len, bufsize);
- 		return false;
- 	}
- 	return true;
-@@ -1637,14 +1650,21 @@ void *ad_entry(const struct adouble *ad, int eid)
- 	size_t len = ad_getentrylen(ad, eid);
- 	bool valid;
+ static const struct entry entry_order2[ADEID_NUM_V2 + 1] = {
+     {ADEID_NAME,        ADEDOFF_NAME_V2,     ADEDLEN_INIT},
+-    {ADEID_COMMENT,     ADEDOFF_COMMENT_V2,  ADEDLEN_INIT},
++    {ADEID_COMMENT,     ADEDOFF_COMMENT_V2,  ADEDLEN_COMMENT},
+     {ADEID_FILEDATESI,  ADEDOFF_FILEDATESI,  ADEDLEN_FILEDATESI},
+     {ADEID_FINDERI,     ADEDOFF_FINDERI_V2,  ADEDLEN_FINDERI},
+     {ADEID_DID,         ADEDOFF_DID,         ADEDLEN_DID},
+     {ADEID_AFPFILEI,    ADEDOFF_AFPFILEI,    ADEDLEN_AFPFILEI},
+     {ADEID_SHORTNAME,   ADEDOFF_SHORTNAME,   ADEDLEN_INIT},
+     {ADEID_PRODOSFILEI, ADEDOFF_PRODOSFILEI, ADEDLEN_PRODOSFILEI},
+-    {ADEID_PRIVDEV,     ADEDOFF_PRIVDEV,     ADEDLEN_INIT},
+-    {ADEID_PRIVINO,     ADEDOFF_PRIVINO,     ADEDLEN_INIT},
+-    {ADEID_PRIVSYN,     ADEDOFF_PRIVSYN,     ADEDLEN_INIT},
+-    {ADEID_PRIVID,      ADEDOFF_PRIVID,      ADEDLEN_INIT},
++    {ADEID_PRIVDEV,     ADEDOFF_PRIVDEV,     ADEDLEN_PRIVDEV},
++    {ADEID_PRIVINO,     ADEDOFF_PRIVINO,     ADEDLEN_PRIVINO},
++    {ADEID_PRIVSYN,     ADEDOFF_PRIVSYN,     ADEDLEN_PRIVSYN},
++    {ADEID_PRIVID,      ADEDOFF_PRIVID,      ADEDLEN_PRIVID},
+     {ADEID_RFORK,       ADEDOFF_RFORK_V2,    ADEDLEN_INIT},
+     {0, 0, 0}
+ };
+@@ -158,13 +158,13 @@ static const struct entry entry_order2[ADEID_NUM_V2 + 
+ /* Using Extended Attributes */
+ static const struct entry entry_order_ea[ADEID_NUM_EA + 1] = {
+     {ADEID_FINDERI,    ADEDOFF_FINDERI_EA,    ADEDLEN_FINDERI},
+-    {ADEID_COMMENT,    ADEDOFF_COMMENT_EA,    ADEDLEN_INIT},
++    {ADEID_COMMENT,    ADEDOFF_COMMENT_EA,    ADEDLEN_COMMENT},
+     {ADEID_FILEDATESI, ADEDOFF_FILEDATESI_EA, ADEDLEN_FILEDATESI},
+     {ADEID_AFPFILEI,   ADEDOFF_AFPFILEI_EA,   ADEDLEN_AFPFILEI},
+-    {ADEID_PRIVDEV,    ADEDOFF_PRIVDEV_EA,    ADEDLEN_INIT},
+-    {ADEID_PRIVINO,    ADEDOFF_PRIVINO_EA,    ADEDLEN_INIT},
+-    {ADEID_PRIVSYN,    ADEDOFF_PRIVSYN_EA,    ADEDLEN_INIT},
+-    {ADEID_PRIVID,     ADEDOFF_PRIVID_EA,     ADEDLEN_INIT},
++    {ADEID_PRIVDEV,    ADEDOFF_PRIVDEV_EA,    ADEDLEN_PRIVDEV},
++    {ADEID_PRIVINO,    ADEDOFF_PRIVINO_EA,    ADEDLEN_PRIVINO},
++    {ADEID_PRIVSYN,    ADEDOFF_PRIVSYN_EA,    ADEDLEN_PRIVSYN},
++    {ADEID_PRIVID,     ADEDOFF_PRIVID_EA,     ADEDLEN_PRIVID},
+     {0, 0, 0}
+ };
  
-+	if (bufsize == 0) {
-+		bufsize = sizeof(ad->ad_data) - (off + len);
-+	}
+@@ -360,15 +360,22 @@ static int new_ad_header(struct adouble *ad, const cha
+     const struct entry  *eid;
+     uint16_t            ashort;
+     struct stat         st;
++    char                *adp = NULL;
+ 
+     LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path);
+ 
+     if (ad_init_offsets(ad) != 0)
+         return -1;
+ 
++    if (ad->valid_data_len == 0) {
++        ad->valid_data_len = ad->ad_vers == AD_VERSION_EA ? AD_DATASZ_EA : AD_DATASZ2;
++    }
++    adp = ad_entry(ad, ADEID_FINDERI);
++    AFP_ASSERT(adp != NULL);
 +
- 	valid = ad_entry_check_size(eid, bufsize, off, len);
- 	if (!valid) {
-+		LOG(log_error, logtype_ad, "ad_entry: not valid");
- 		return NULL;
- 	}
+     /* set default creator/type fields */
+-    memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4);
+-    memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4);
++    memcpy(adp + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4);
++    memcpy(adp + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4);
+ 
+     /* make things invisible */
+     if ((ad->ad_options & ADVOL_INVDOTS)
+@@ -378,14 +385,16 @@ static int new_ad_header(struct adouble *ad, const cha
+         ashort = htons(ATTRBIT_INVISIBLE);
+         ad_setattr(ad, ashort);
+         ashort = htons(FINDERINFO_INVISIBLE);
+-        memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
++        memcpy(adp + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
+     }
  
--	if (off == 0 || len == 0) {
-+	/*if (off == 0 || len == 0) {
-+		LOG(log_error, logtype_ad, "ad_entry: off or len is 0 (off: %d, len: %d)",
-+                    off, len);
- 		return NULL;
--	}
-+	}*/
+     /* put something sane in the date fields */
+     if (stp == NULL) {
+         stp = &st;
+-        if (lstat(path, &st) != 0)
++        if (lstat(path, &st) != 0) {
++            ad->valid_data_len = 0;
+             return -1;
++        }
+     }
+     ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, stp->st_mtime);
+     ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, stp->st_mtime);
+@@ -417,7 +426,7 @@ static int parse_entries(struct adouble *ad, uint16_t 
  
- 	return ((struct adouble *)ad)->ad_data + off;
- }
+         if (!eid
+             || eid > ADEID_MAX
+-            || off >= valid_data_len
++            || ((eid != ADEID_RFORK) && (off >= valid_data_len))
+             || ((eid != ADEID_RFORK) && (off + len >  valid_data_len)))
+         {
+             LOG(log_warning, logtype_ad, "parse_entries: bogus eid: %u, off: %u, len: %u",